You are looking at historical revision 26924 of this page. It may differ significantly from its current revision.

FOX

Author

Joo ChurlSoo

Changes

The optional arguments of the original CAT procedure were divided into three groups; arguments only for the number type of <object>, arguments for all types except the number type of <object>, and arguments for all types of <object>. This complexity can make users confused. Those of this revised one are divided into two groups; arguments only for the number type of <object> and arguments for all types of <object>. This simplicity also makes <writer> to be able to substitute for <converter>. The <precision> actually serves as ~G of Common Lisp's FORMAT and %G of C's PRINTF. The <point> of this revised one, an additional optional argument, serves as ~F or ~E of Common Lisp's FORMAT and %F or %E of C's PRINTF. This revised CAT procedure, FOX is for speed up of non-number type of object. For the purpose, the optional arguments only for the number type of object integrate into a list type argument, <merge>.

Additional extensions:

1. All optional arguments can be applied to the number type of <object>.

2. The default value of <writer> is DISPLAY procedure.

3. The <width> is an integer, and the <precision> is a non-negative exact

  integer.

4. The new optional arguments, <point> ('fixed or 'float), <pre-string>, and

  <post-string> are added.

5. The <take> is changed from a list to a pair, and its elements are exact

  integers, strings, or procedures.

6. The <separator> is changed from a list to a vector, and the second element

  of <separator> is a non-zero exact integer.

7. Infinities and nans of R6RS are supported.

8. The <pipe> is integrated into the <take>.

9. The <converter> is integrated into the <writer>.

Abstract

This introduces the FOX procedure that takes one object as the first argument and accepts a variable number of optional arguments, and returns a string.

Rationale

It is difficult to gain a complete consensus for the design of a generic formatting procedure that performs a variety of functions provided in C's PRINTF and Common lisp's FORMAT. One of such ways would be to devise a free non-sequent method that easily handles optional arguments, in contrast to the conventional fixed sequent method, in order to obtain a handy optional and functional interface.

Specification

<procedure> (FOX <object>

    [<pre-string>]
    [<port>] [<width>] [<char>] [<writer>] [<merge>] [<take>] [<separator>]
    [<post-string>] ...)

<merge> --> ([<precision>] [<point>] [<radix>] [<sign>] [<exactness>]) </procedure>

The <merge> is a list whose elements are <precision>, <point>, <radix>, <sign>, and <exactness>. The <precision> <point> <radix> <sign> <exactness> are effective only for the number type of <object>. Except <string>s, the order of all other optional arguments does not matter. When there is a <string> or <string>s without the other optional arguments, the <string> or <string>s are <post-string>. The FOX process the optional arguments in the following order; <writer>, <exactness>, <point>, <precision>, <radix>, <separator>, <sign>, <take>, <width>, <char>, <string>, <port>.

1. The <object> is any Scheme object.

2. The <width> is an integer whose absolute value specifies the width of the

   resulting string.  When the resulting string has fewer characters than the
   absolute value of <width>, it is placed rightmost with the rest being
   padded with <char>s, if <width> is positive, or it is placed leftmost with
   the rest being padded with <char>s, if <width> is negative, or it is
   placed in the center (near to right in case of positive <width>, or near
   to left in case of negative <width>) with the rest being padded with
   <char>s, if <width> is an inexact integer.  On the other hand, when the
   resulting string has more characters than the absolute value of <width>,
   the <width> is ignored.  The default value is 0.

3. The <writer> is a procedure of two arguments; <object> and a string port.

   It writes <object> to the string port.  The default value is DISPLAY
   procedure.  If you want any objects to be displayed in your own way, you
   have to define your own <writer>.  Otherwise, they are displayed simply in
   their evaluated forms.  When <writer> except DISPLAY and WRITE procedures
   is used, the optional arguments that are effective only for the number type
   of <object> become ineffective.
  

4. The <port> is an output port or a boolean. If an output port is specified,

   the resulting string is output into the port.  If <port> is #t, the output
   port is current output port.  If <port> is #f, the resulting string is
   returned.  The default value is #f.

5. The <char> is a padding character. The default value is #\space.

6. The <take> is a pair whose car and cdr values are exact integers or

   strings or procedures; m and n, and the absolute values of m and n are M
   and N, respectively.
   First,
   When the car element is an exact integer, the resulting string takes from
   the left m-characters, if it is positive, or all the characters but
   M-characters, if non-positive.
   When the car element is a string, the string is prefixed.
   When the car element is a procedure, the procedure takes a string argument
   and returns a string as a pipe.
   Second,
   When the cdr element is an exact integer, the resulting string takes from
   the right n-characters of the string that is processed by the car element,
   if it is positive, or all the characters but N-characters, if non-positive.
   When the cdr element is a string, the string is postfixed to the string
   that is processed by the car element.
   When the cdr element is a procedure, the procedure takes the string
   processed by the car element as an argument and returns a string.
  

7. The <separator> is a vector whose first element is a string serving as a

   separator and second element is a non-zero exact integer; n, and the
   absolute value of n is N.  The resulting string is separated in every
   N-characters of the resulting string from right end, if n is positive, or
   from left end, if n is negative.  Even if n is a negative integer, its
   absolute value is used for the number type of <object>.  When the integer
   is omitted, the <separator> is effective only for the number type of
   <object> and its default value is 3.

8. The <point> is a symbol: fixed or float. Each returns a string of decimal

   fraction or exponential representation.

9. The <precision> is a non-negative exact integer that specifies the number

  of decimal digits after a decimal point.

10. The <radix> is a symbol: binary, octal, decimal, or hexadecimal. Each

   radix sign except decimal is prefixed to the resulting string.  The
   default value is decimal.

11. If <sign> is a symbol that takes the form of 'sign, and <object> is a

   positive number without a positive sign, the positive sign is prefixed to
   the resulting string.

12. The <exactness> is a symbol: exact or inexact. Each returns a string of

   exact or inexact representation.

13. The resulting string is prefixed with <pre-string> and postfixed with

   <post-string>s.

Examples

{{{ (fox 129.995 -10 '(1)) -> "130.0 " (fox 129.995 10 '(1)) -> " 130.0" (fox 129.995 -10. #\* '(1)) -> "**130.0***" (fox 129.995 10. #\* '(1)) -> "***130.0**" (fox 129.995 10. #\* '(2)) -> "**130.00**"

(fox 4048 10 #\* '(hexadecimal)) -> "*****#xfd0" (fox 4048 10 #\* '(hexadecimal sign)) -> "****#x+fd0" (fox 4048 10 #\0 '(hexadecimal sign)) -> "#x+0000fd0" (fox 4048.3125 15 #\* '(hexadecimal)) -> "****#i#xfd05/10" (fox 4048.3125 15 #\* '(hexadecimal exact)) -> "******#xfd05/10" (fox 4048 10 #\0 '(hexadecimal sign) `(,string-upcase . 0)) -> "#X+0000FD0" (fox 4048 10 #\Z '(hexadecimal sign) `(,string-upcase . 0)) -> "ZZZZ#X+FD0" (fox 4048 10 #\B '(hexadecimal sign) `(,string-upcase . 0)) -> "#X+BBBBFD0"

(fox 129.995 10 '(2 sign) '("$" . 0)) -> " $+130.00" (fox 129.995 10 '(2 sign) '("$" . -3)) -> " $+130"

(fox 123000000 '(float)) -> "1.23e+8" (fox 123000000 '(5 float)) -> "1.23000e+8" (fox 1.23456789e+25 '(fixed)) -> "12345678900000000000000000.0"

(fox 129.995 10. #\* '(0) '("|" . "|")) -> "**|130.|**" (fox 129.995 "|" 10. #\* '(0) "|") -> "|***130.***|"

(fox 123456789.012 '(sign) '#(",")) -> "+123,456,789.012" (fox 123456789 '(sign) '#("," 4)) -> "+1,2345,6789" (fox "abcdefg" '(sign) '#(",")) -> "abcdefg" (fox "abcdefg" '(sign) '#("::" 2)) -> "a::bc::de::fg" (fox "abcdefg" '(sign) '#("::" -2)) -> "ab::cd::ef::g"

(fox '(#\a "str" s)) -> "(a str s)" (fox '(#\a "str" s) write) -> "(#\\a \"str\" s)"

(fox 'String "^" (current-output-port) 10 #\0 "$") -> ^0000String$ (fox 'String "^" #t 10 #\* "$") -> ^****String$

(define-record-type example

 (make-example num str)
 example?
 (num get-num set-num!)
 (str get-str set-str!))

(define (record-writer object string-port)

 (if (example? object)
     (begin (display (get-num object) string-port)
     (display "-" string-port)
     (display (get-str object) string-port))
     (display object string-port)))

(define (record-display object string-port)

 (display (get-num object) string-port)
 (display "-" string-port)
 (display (get-str object) string-port))

(let ((plus 12345678.901)

     (minus -123456.789)
     (ex (make-example 1234 "ex"))
     (file "today.txt"))
 (for-each (lambda (x y)
      (fox x #t 10)
      (fox y #t 15 '(2) (if (example? y) record-display display) '#(","))
      (fox x #t 10)
      (fox y #t 15 '(2) record-writer '#(","))
      (newline))
    (list "plus: " "minus: " "net: " "ex: " "file: ")
    (list plus minus (+ plus minus) ex file)))

->

   plus:   12,345,678.90    plus:  12,345,678.901
  minus:     -123,456.79   minus:    -123,456.789
    net:   12,222,222.11     net:  12,222,222.112
     ex:         1234-ex      ex:         1234-ex
   file:       today.txt    file:       today.txt

}}}

References

[R5RS] Richard Kelsey, William Clinger, and Jonathan Rees: Revised(5)

    Report on the Algorithmic Language Scheme
    http://www.schemers.org/Documents/Standards/R5Rs/

[R6RS] Michael Sperber, R. Kent Dybvig, Matthew Flatt, and

    Anton von Straaten:
    Revised(6) Report on the Algorithmic Language Scheme
    http://www.r6rs.org

Copyright (c) 2012 Joo ChurlSoo.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ``Software''), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.