This is guile.info, produced by makeinfo version 5.2 from guile.texi.

This manual documents Guile version 2.0.11.

   Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2009,
2010, 2011, 2012, 2013, 2014 Free Software Foundation.

   Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.  A
copy of the license is included in the section entitled “GNU Free
Documentation License.”
INFO-DIR-SECTION The Algorithmic Language Scheme
START-INFO-DIR-ENTRY
* Guile Reference: (guile).     The Guile reference manual.
END-INFO-DIR-ENTRY


File: guile.info,  Node: Pretty Printing,  Next: Formatted Output,  Prev: Readline Support,  Up: Guile Modules

7.9 Pretty Printing
===================

The module ‘(ice-9 pretty-print)’ provides the procedure ‘pretty-print’,
which provides nicely formatted output of Scheme objects.  This is
especially useful for deeply nested or complex data structures, such as
lists and vectors.

   The module is loaded by entering the following:

     (use-modules (ice-9 pretty-print))

   This makes the procedure ‘pretty-print’ available.  As an example how
‘pretty-print’ will format the output, see the following:

     (pretty-print '(define (foo) (lambda (x)
     (cond ((zero? x) #t) ((negative? x) -x) (else
     (if (= x 1) 2 (* x x x)))))))
     ⊣
     (define (foo)
       (lambda (x)
         (cond ((zero? x) #t)
               ((negative? x) -x)
               (else (if (= x 1) 2 (* x x x))))))

 -- Scheme Procedure: pretty-print obj [port] [keyword-options]
     Print the textual representation of the Scheme object OBJ to PORT.
     PORT defaults to the current output port, if not given.

     The further KEYWORD-OPTIONS are keywords and parameters as follows,

     #:display? FLAG
          If FLAG is true then print using ‘display’.  The default is
          ‘#f’ which means use ‘write’ style.  (*note Writing::)

     #:per-line-prefix STRING
          Print the given STRING as a prefix on each line.  The default
          is no prefix.

     #:width COLUMNS
          Print within the given COLUMNS.  The default is 79.

   Also exported by the ‘(ice-9 pretty-print)’ module is
‘truncated-print’, a procedure to print Scheme datums, truncating the
output to a certain number of characters.  This is useful when you need
to present an arbitrary datum to the user, but you only have one line in
which to do so.

     (define exp '(a b #(c d e) f . g))
     (truncated-print exp #:width 10) (newline)
     ⊣ (a b . #)
     (truncated-print exp #:width 15) (newline)
     ⊣ (a b # f . g)
     (truncated-print exp #:width 18) (newline)
     ⊣ (a b #(c ...) . #)
     (truncated-print exp #:width 20) (newline)
     ⊣ (a b #(c d e) f . g)
     (truncated-print "The quick brown fox" #:width 20) (newline)
     ⊣ "The quick brown..."
     (truncated-print (current-module) #:width 20) (newline)
     ⊣ #<directory (gui...>

   ‘truncated-print’ will not output a trailing newline.  If an
expression does not fit in the given width, it will be truncated –
possibly ellipsized(1), or in the worst case, displayed as #.

 -- Scheme Procedure: truncated-print obj [port] [keyword-options]
     Print OBJ, truncating the output, if necessary, to make it fit into
     WIDTH characters.  By default, OBJ will be printed using ‘write’,
     though that behavior can be overridden via the DISPLAY? keyword
     argument.

     The default behaviour is to print depth-first, meaning that the
     entire remaining width will be available to each sub-expression of
     OBJ – e.g., if OBJ is a vector, each member of OBJ.  One can
     attempt to “ration” the available width, trying to allocate it
     equally to each sub-expression, via the BREADTH-FIRST? keyword
     argument.

     The further KEYWORD-OPTIONS are keywords and parameters as follows,

     #:display? FLAG
          If FLAG is true then print using ‘display’.  The default is
          ‘#f’ which means use ‘write’ style.  (*note Writing::)

     #:width COLUMNS
          Print within the given COLUMNS.  The default is 79.

     #:breadth-first? FLAG
          If FLAG is true, then allocate the available width
          breadth-first among elements of a compound data structure
          (list, vector, pair, etc.).  The default is ‘#f’ which means
          that any element is allowed to consume all of the available
          width.

   ---------- Footnotes ----------

   (1) On Unicode-capable ports, the ellipsis is represented by
character ‘HORIZONTAL ELLIPSIS’ (U+2026), otherwise it is represented by
three dots.


File: guile.info,  Node: Formatted Output,  Next: File Tree Walk,  Prev: Pretty Printing,  Up: Guile Modules

7.10 Formatted Output
=====================

The ‘format’ function is a powerful way to print numbers, strings and
other objects together with literal text under the control of a format
string.  This function is available from

     (use-modules (ice-9 format))

   A format string is generally more compact and easier than using just
the standard procedures like ‘display’, ‘write’ and ‘newline’.
Parameters in the output string allow various output styles, and
parameters can be taken from the arguments for runtime flexibility.

   ‘format’ is similar to the Common Lisp procedure of the same name,
but it’s not identical and doesn’t have quite all the features found in
Common Lisp.

   C programmers will note the similarity between ‘format’ and ‘printf’,
though escape sequences are marked with ~ instead of %, and are more
powerful.


 -- Scheme Procedure: format dest fmt arg …
     Write output specified by the FMT string to DEST.  DEST can be an
     output port, ‘#t’ for ‘current-output-port’ (*note Default
     Ports::), or ‘#f’ to return the output as a string.

     FMT can contain literal text to be output, and ~ escapes.  Each
     escape has the form

          ~ [param [, param…] [:] [@] code

     code is a character determining the escape sequence.  The : and @
     characters are optional modifiers, one or both of which change the
     way various codes operate.  Optional parameters are accepted by
     some codes too.  Parameters have the following forms,

     [+/-]number
          An integer, with optional + or -.
     ’ (apostrophe)
          The following character in the format string, for instance ’z
          for z.
     v
          The next function argument as the parameter.  v stands for
          “variable”, a parameter can be calculated at runtime and
          included in the arguments.  Upper case V can be used too.
     #
          The number of arguments remaining.  (See ~* below for some
          usages.)

     Parameters are separated by commas (,).  A parameter can be left
     empty to keep its default value when supplying later parameters.


     The following escapes are available.  The code letters are not
     case-sensitive, upper and lower case are the same.

     ~a
     ~s
          Object output.  Parameters: MINWIDTH, PADINC, MINPAD, PADCHAR.

          ~a outputs an argument like ‘display’, ~s outputs an argument
          like ‘write’ (*note Writing::).

               (format #t "~a" "foo") ⊣ foo
               (format #t "~s" "foo") ⊣ "foo"

          ~:a and ~:s put objects that don’t have an external
          representation in quotes like a string.

               (format #t "~:a" car) ⊣ "#<primitive-procedure car>"

          If the output is less than MINWIDTH characters (default 0),
          it’s padded on the right with PADCHAR (default space).  ~@a
          and ~@s put the padding on the left instead.

               (format #f "~5a" 'abc)       ⇒ "abc  "
               (format #f "~5,,,'-@a" 'abc) ⇒ "--abc"

          MINPAD is a minimum for the padding then plus a multiple of
          PADINC.  Ie. the padding is MINPAD + N * PADINC, where N is
          the smallest integer making the total object plus padding
          greater than or equal to MINWIDTH.  The default MINPAD is 0
          and the default PADINC is 1 (imposing no minimum or multiple).

               (format #f "~5,1,4a" 'abc) ⇒ "abc    "

     ~c
          Character.  Parameter: CHARNUM.

          Output a character.  The default is to simply output, as per
          ‘write-char’ (*note Writing::).  ~@c prints in ‘write’ style.
          ~:c prints control characters (ASCII 0 to 31) in ^X form.

               (format #t "~c" #\z)        ⊣ z
               (format #t "~@c" #\z)       ⊣ #\z
               (format #t "~:c" #\newline) ⊣ ^J

          If the CHARNUM parameter is given then an argument is not
          taken but instead the character is ‘(integer->char CHARNUM)’
          (*note Characters::).  This can be used for instance to output
          characters given by their ASCII code.

               (format #t "~65c")  ⊣ A

     ~d
     ~x
     ~o
     ~b
          Integer.  Parameters: MINWIDTH, PADCHAR, COMMACHAR,
          COMMAWIDTH.

          Output an integer argument as a decimal, hexadecimal, octal or
          binary integer (respectively), in a locale-independent way.

               (format #t "~d" 123) ⊣ 123

          ~@d etc shows a + sign is shown on positive numbers.

               (format #t "~@b" 12) ⊣ +1100

          If the output is less than the MINWIDTH parameter (default no
          minimum), it’s padded on the left with the PADCHAR parameter
          (default space).

               (format #t "~5,'*d" 12)   ⊣ ***12
               (format #t "~5,'0d" 12)   ⊣ 00012
               (format #t "~3d"    1234) ⊣ 1234

          ~:d adds commas (or the COMMACHAR parameter) every three
          digits (or the COMMAWIDTH parameter many).  However, when your
          intent is to write numbers in a way that follows typographical
          conventions, using ~h is recommended.

               (format #t "~:d" 1234567)         ⊣ 1,234,567
               (format #t "~10,'*,'/,2:d" 12345) ⊣ ***1/23/45

          Hexadecimal ~x output is in lower case, but the ~( and ~) case
          conversion directives described below can be used to get upper
          case.

               (format #t "~x"       65261) ⊣ feed
               (format #t "~:@(~x~)" 65261) ⊣ FEED

     ~r
          Integer in words, roman numerals, or a specified radix.
          Parameters: RADIX, MINWIDTH, PADCHAR, COMMACHAR, COMMAWIDTH.

          With no parameters output is in words as a cardinal like
          “ten”, or ~:r prints an ordinal like “tenth”.

               (format #t "~r" 9)  ⊣ nine        ;; cardinal
               (format #t "~r" -9) ⊣ minus nine  ;; cardinal
               (format #t "~:r" 9) ⊣ ninth       ;; ordinal

          And also with no parameters, ~@r gives roman numerals and ~:@r
          gives old roman numerals.  In old roman numerals there’s no
          “subtraction”, so 9 is VIIII instead of IX. In both cases only
          positive numbers can be output.

               (format #t "~@r" 89)  ⊣ LXXXIX     ;; roman
               (format #t "~:@r" 89) ⊣ LXXXVIIII  ;; old roman

          When a parameter is given it means numeric output in the
          specified RADIX.  The modifiers and parameters following the
          radix are the same as described for ~d etc above.

               (format #f "~3r" 27)   ⇒ "1000"    ;; base 3
               (format #f "~3,5r" 26) ⇒ "  222"   ;; base 3 width 5

     ~f
          Fixed-point float.  Parameters: WIDTH, DECIMALS, SCALE,
          OVERFLOWCHAR, PADCHAR.

          Output a number or number string in fixed-point format, ie.
          with a decimal point.

               (format #t "~f" 5)      ⊣ 5.0
               (format #t "~f" "123")  ⊣ 123.0
               (format #t "~f" "1e-1") ⊣ 0.1

          ~@f prints a + sign on positive numbers (including zero).

               (format #t "~@f" 0) ⊣ +0.0

          If the output is less than WIDTH characters it’s padded on the
          left with PADCHAR (space by default).  If the output equals or
          exceeds WIDTH then there’s no padding.  The default for WIDTH
          is no padding.

               (format #f "~6f" -1.5)      ⇒ "  -1.5"
               (format #f "~6,,,,'*f" 23)  ⇒ "**23.0"
               (format #f "~6f" 1234567.0) ⇒ "1234567.0"

          DECIMALS is how many digits to print after the decimal point,
          with the value rounded or padded with zeros as necessary.
          (The default is to output as many decimals as required.)

               (format #t "~1,2f" 3.125) ⊣ 3.13
               (format #t "~1,2f" 1.5)   ⊣ 1.50

          SCALE is a power of 10 applied to the value, moving the
          decimal point that many places.  A positive SCALE increases
          the value shown, a negative decreases it.

               (format #t "~,,2f" 1234)  ⊣ 123400.0
               (format #t "~,,-2f" 1234) ⊣ 12.34

          If OVERFLOWCHAR and WIDTH are both given and if the output
          would exceed WIDTH, then that many OVERFLOWCHARs are printed
          instead of the value.

               (format #t "~6,,,'xf" 12345) ⊣ 12345.
               (format #t "~5,,,'xf" 12345) ⊣ xxxxx

     ~h
          Localized number(1).  Parameters: WIDTH, DECIMALS, PADCHAR.

          Like ~f, output an exact or floating point number, but do so
          according to the current locale, or according to the given
          locale object when the ‘:’ modifier is used (*note
          ‘number->locale-string’: Number Input and Output.).

               (format #t "~h" 12345.5678)  ; with "C" as the current locale
               ⊣ 12345.5678

               (format #t "~14,,'*:h" 12345.5678
                       (make-locale LC_ALL "en_US"))
               ⊣ ***12,345.5678

               (format #t "~,2:h" 12345.5678
                       (make-locale LC_NUMERIC "fr_FR"))
               ⊣ 12 345,56

     ~e
          Exponential float.  Parameters: WIDTH, MANTDIGITS, EXPDIGITS,
          INTDIGITS, OVERFLOWCHAR, PADCHAR, EXPCHAR.

          Output a number or number string in exponential notation.

               (format #t "~e" 5000.25) ⊣ 5.00025E+3
               (format #t "~e" "123.4") ⊣ 1.234E+2
               (format #t "~e" "1e4")   ⊣ 1.0E+4

          ~@e prints a + sign on positive numbers (including zero).
          (This is for the mantissa, a + or - sign is always shown on
          the exponent.)

               (format #t "~@e" 5000.0) ⊣ +5.0E+3

          If the output is less than WIDTH characters it’s padded on the
          left with PADCHAR (space by default).  The default for WIDTH
          is to output with no padding.

               (format #f "~10e" 1234.0)     ⇒ "  1.234E+3"
               (format #f "~10,,,,,'*e" 0.5) ⇒ "****5.0E-1"

          MANTDIGITS is the number of digits shown in the mantissa after
          the decimal point.  The value is rounded or trailing zeros are
          added as necessary.  The default MANTDIGITS is to show as much
          as needed by the value.

               (format #f "~,3e" 11111.0) ⇒ "1.111E+4"
               (format #f "~,8e" 123.0)   ⇒ "1.23000000E+2"

          EXPDIGITS is the minimum number of digits shown for the
          exponent, with leading zeros added if necessary.  The default
          for EXPDIGITS is to show only as many digits as required.  At
          least 1 digit is always shown.

               (format #f "~,,1e" 1.0e99) ⇒ "1.0E+99"
               (format #f "~,,6e" 1.0e99) ⇒ "1.0E+000099"

          INTDIGITS (default 1) is the number of digits to show before
          the decimal point in the mantissa.  INTDIGITS can be zero, in
          which case the integer part is a single 0, or it can be
          negative, in which case leading zeros are shown after the
          decimal point.

               (format #t "~,,,3e" 12345.0)  ⊣ 123.45E+2
               (format #t "~,,,0e" 12345.0)  ⊣ 0.12345E+5
               (format #t "~,,,-3e" 12345.0) ⊣ 0.00012345E+8

          If OVERFLOWCHAR is given then WIDTH is a hard limit.  If the
          output would exceed WIDTH then instead that many OVERFLOWCHARs
          are printed.

               (format #f "~6,,,,'xe" 100.0) ⇒ "1.0E+2"
               (format #f "~3,,,,'xe" 100.0) ⇒ "xxx"

          EXPCHAR is the exponent marker character (default E).

               (format #t "~,,,,,,'ee" 100.0) ⊣ 1.0e+2

     ~g
          General float.  Parameters: WIDTH, MANTDIGITS, EXPDIGITS,
          INTDIGITS, OVERFLOWCHAR, PADCHAR, EXPCHAR.

          Output a number or number string in either exponential format
          the same as ~e, or fixed-point format like ~f but aligned
          where the mantissa would have been and followed by padding
          where the exponent would have been.

          Fixed-point is used when the absolute value is 0.1 or more and
          it takes no more space than the mantissa in exponential
          format, ie. basically up to MANTDIGITS digits.

               (format #f "~12,4,2g" 999.0)    ⇒ "   999.0    "
               (format #f "~12,4,2g" "100000") ⇒ "  1.0000E+05"

          The parameters are interpreted as per ~e above.  When
          fixed-point is used, the DECIMALS parameter to ~f is
          established from MANTDIGITS, so as to give a total
          MANTDIGITS+1 figures.

     ~$
          Monetary style fixed-point float.  Parameters: DECIMALS,
          INTDIGITS, WIDTH, PADCHAR.

          Output a number or number string in fixed-point format, ie.
          with a decimal point.  DECIMALS is the number of decimal
          places to show, default 2.

               (format #t "~$" 5)       ⊣ 5.00
               (format #t "~4$" "2.25") ⊣ 2.2500
               (format #t "~4$" "1e-2") ⊣ 0.0100

          ~@$ prints a + sign on positive numbers (including zero).

               (format #t "~@$" 0) ⊣ +0.00

          INTDIGITS is a minimum number of digits to show in the integer
          part of the value (default 1).

               (format #t "~,3$" 9.5)   ⊣ 009.50
               (format #t "~,0$" 0.125) ⊣ .13

          If the output is less than WIDTH characters (default 0), it’s
          padded on the left with PADCHAR (default space).  ~:$ puts the
          padding after the sign.

               (format #f "~,,8$" -1.5)   ⇒ "   -1.50"
               (format #f "~,,8:$" -1.5)  ⇒ "-   1.50"
               (format #f "~,,8,'.:@$" 3) ⇒ "+...3.00"

          Note that floating point for dollar amounts is generally not a
          good idea, because a cent 0.01 cannot be represented exactly
          in the binary floating point Guile uses, which leads to slowly
          accumulating rounding errors.  Keeping values as cents (or
          fractions of a cent) in integers then printing with the scale
          option in ~f may be a better approach.

     ~i
          Complex fixed-point float.  Parameters: WIDTH, DECIMALS,
          SCALE, OVERFLOWCHAR, PADCHAR.

          Output the argument as a complex number, with both real and
          imaginary part shown (even if one or both are zero).

          The parameters and modifiers are the same as for fixed-point
          ~f described above.  The real and imaginary parts are both
          output with the same given parameters and modifiers, except
          that for the imaginary part the @ modifier is always enabled,
          so as to print a + sign between the real and imaginary parts.

               (format #t "~i" 1)  ⊣ 1.0+0.0i

     ~p
          Plural.  No parameters.

          Output nothing if the argument is 1, or ‘s’ for any other
          value.

               (format #t "enter name~p" 1) ⊣ enter name
               (format #t "enter name~p" 2) ⊣ enter names

          ~@p prints ‘y’ for 1 or ‘ies’ otherwise.

               (format #t "pupp~@p" 1) ⊣ puppy
               (format #t "pupp~@p" 2) ⊣ puppies

          ~:p re-uses the preceding argument instead of taking a new
          one, which can be convenient when printing some sort of count.

               (format #t "~d cat~:p" 9)   ⊣ 9 cats
               (format #t "~d pupp~:@p" 5) ⊣ 5 puppies

          ~p is designed for English plurals and there’s no attempt to
          support other languages.  ~[ conditionals (below) may be able
          to help.  When using ‘gettext’ to translate messages
          ‘ngettext’ is probably best though (*note
          Internationalization::).

     ~y
          Structured printing.  Parameters: WIDTH.

          ~y outputs an argument using ‘pretty-print’ (*note Pretty
          Printing::).  The result will be formatted to fit within WIDTH
          columns (79 by default), consuming multiple lines if
          necessary.

          ~@y outputs an argument using ‘truncated-print’ (*note Pretty
          Printing::).  The resulting code will be formatted to fit
          within WIDTH columns (79 by default), on a single line.  The
          output will be truncated if necessary.

          ~:@y is like ~@y, except the WIDTH parameter is interpreted to
          be the maximum column to which to output.  That is to say, if
          you are at column 10, and ~60:@y is seen, the datum will be
          truncated to 50 columns.

     ~?
     ~k
          Sub-format.  No parameters.

          Take a format string argument and a second argument which is a
          list of arguments for that string, and output the result.

               (format #t "~?" "~d ~d" '(1 2))    ⊣ 1 2

          ~@?  takes arguments for the sub-format directly rather than
          in a list.

               (format #t "~@? ~s" "~d ~d" 1 2 "foo") ⊣ 1 2 "foo"

          ~?  and ~k are the same, ~k is provided for T-Scheme
          compatibility.

     ~*
          Argument jumping.  Parameter: N.

          Move forward N arguments (default 1) in the argument list.
          ~:* moves backwards.  (N cannot be negative.)

               (format #f "~d ~2*~d" 1 2 3 4) ⇒ "1 4"
               (format #f "~d ~:*~d" 6)       ⇒ "6 6"

          ~@* moves to argument number N.  The first argument is number
          0 (and that’s the default for N).

               (format #f "~d~d again ~@*~d~d" 1 2) ⇒ "12 again 12"
               (format #f "~d~d~d ~1@*~d~d" 1 2 3)  ⇒ "123 23"

          A # move to the end followed by a : modifier move back can be
          used for an absolute position relative to the end of the
          argument list, a reverse of what the @ modifier does.

               (format #t "~#*~2:*~a" 'a 'b 'c 'd)   ⊣ c

          At the end of the format string the current argument position
          doesn’t matter, any further arguments are ignored.

     ~t
          Advance to a column position.  Parameters: COLNUM, COLINC,
          PADCHAR.

          Output PADCHAR (space by default) to move to the given COLNUM
          column.  The start of the line is column 0, the default for
          COLNUM is 1.

               (format #f "~tX")  ⇒ " X"
               (format #f "~3tX") ⇒ "   X"

          If the current column is already past COLNUM, then the move is
          to there plus a multiple of COLINC, ie. column COLNUM + N *
          COLINC for the smallest N which makes that value greater than
          or equal to the current column.  The default COLINC is 1
          (which means no further move).

               (format #f "abcd~2,5,'.tx") ⇒ "abcd...x"

          ~@t takes COLNUM as an offset from the current column.  COLNUM
          many pad characters are output, then further padding to make
          the current column a multiple of COLINC, if it isn’t already
          so.

               (format #f "a~3,5'*@tx") ⇒ "a****x"

          ~t is implemented using ‘port-column’ (*note Reading::), so it
          works even there has been other output before ‘format’.

     ~~
          Tilde character.  Parameter: N.

          Output a tilde character ~, or N many if a parameter is given.
          Normally ~ introduces an escape sequence, ~~ is the way to
          output a literal tilde.

     ~%
          Newline.  Parameter: N.

          Output a newline character, or N many if a parameter is given.
          A newline (or a few newlines) can of course be output just by
          including them in the format string.

     ~&
          Start a new line.  Parameter: N.

          Output a newline if not already at the start of a line.  With
          a parameter, output that many newlines, but with the first
          only if not already at the start of a line.  So for instance 3
          would be a newline if not already at the start of a line, and
          2 further newlines.

     ~_
          Space character.  Parameter: N.

          Output a space character, or N many if a parameter is given.

          With a variable parameter this is one way to insert runtime
          calculated padding (~t or the various field widths can do
          similar things).

               (format #f "~v_foo" 4) ⇒ "    foo"

     ~/
          Tab character.  Parameter: N.

          Output a tab character, or N many if a parameter is given.

     ~|
          Formfeed character.  Parameter: N.

          Output a formfeed character, or N many if a parameter is
          given.

     ~!
          Force output.  No parameters.

          At the end of output, call ‘force-output’ to flush any buffers
          on the destination (*note Writing::).  ~!  can occur anywhere
          in the format string, but the force is done at the end of
          output.

          When output is to a string (destination ‘#f’), ~!  does
          nothing.

     ~newline (ie. newline character)
          Continuation line.  No parameters.

          Skip this newline and any following whitespace in the format
          string, ie. don’t send it to the output.  This can be used to
          break up a long format string for readability, but not print
          the extra whitespace.

               (format #f "abc~
                           ~d def~
                           ~d" 1 2) ⇒ "abc1 def2"

          ~:newline skips the newline but leaves any further whitespace
          to be printed normally.

          ~@newline prints the newline then skips following whitespace.

     ~( ~)
          Case conversion.  No parameters.

          Between ~( and ~) the case of all output is changed.  The
          modifiers on ~( control the conversion.

               ~( — lower case.
               ~:@( — upper case.

          For example,

               (format #t "~(Hello~)")   ⊣ hello
               (format #t "~:@(Hello~)") ⊣ HELLO

          In the future it’s intended the modifiers : and @ alone will
          capitalize the first letters of words, as per Common Lisp
          ‘format’, but the current implementation of this is flawed and
          not recommended for use.

          Case conversions do not nest, currently.  This might change in
          the future, but if it does then it will be to Common Lisp
          style where the outermost conversion has priority, overriding
          inner ones (making those fairly pointless).

     ~{ ~}
          Iteration.  Parameter: MAXREPS (for ~{).

          The format between ~{ and ~} is iterated.  The modifiers to ~{
          determine how arguments are taken.  The default is a list
          argument with each iteration successively consuming elements
          from it.  This is a convenient way to output a whole list.

               (format #t "~{~d~}"     '(1 2 3))       ⊣ 123
               (format #t "~{~s=~d ~}" '("x" 1 "y" 2)) ⊣ "x"=1 "y"=2

          ~:{ takes a single argument which is a list of lists, each of
          those contained lists gives the arguments for the iterated
          format.

               (format #t "~:{~dx~d ~}" '((1 2) (3 4) (5 6)))
               ⊣ 1x2 3x4 5x6

          ~@{ takes arguments directly, with each iteration successively
          consuming arguments.

               (format #t "~@{~d~}"     1 2 3)       ⊣ 123
               (format #t "~@{~s=~d ~}" "x" 1 "y" 2) ⊣ "x"=1 "y"=2

          ~:@{ takes list arguments, one argument for each iteration,
          using that list for the format.

               (format #t "~:@{~dx~d ~}" '(1 2) '(3 4) '(5 6))
               ⊣ 1x2 3x4 5x6

          Iterating stops when there are no more arguments or when the
          MAXREPS parameter to ~{ is reached (default no maximum).

               (format #t "~2{~d~}" '(1 2 3 4)) ⊣ 12

          If the format between ~{ and ~} is empty, then a format string
          argument is taken (before iteration argument(s)) and used
          instead.  This allows a sub-format (like ~?  above) to be
          iterated.

               (format #t "~{~}" "~d" '(1 2 3)) ⊣ 123

          Iterations can be nested, an inner iteration operates in the
          same way as described, but of course on the arguments the
          outer iteration provides it.  This can be used to work into
          nested list structures.  For example in the following the
          inner ~{~d~}x is applied to ‘(1 2)’ then ‘(3 4 5)’ etc.

               (format #t "~{~{~d~}x~}" '((1 2) (3 4 5))) ⊣ 12x345x

          See also ~^ below for escaping from iteration.

     ~[ ~; ~]
          Conditional.  Parameter: SELECTOR.

          A conditional block is delimited by ~[ and ~], and ~;
          separates clauses within the block.  ~[ takes an integer
          argument and that number clause is used.  The first clause is
          number 0.

               (format #f "~[peach~;banana~;mango~]" 1)  ⇒ "banana"

          The SELECTOR parameter can be used for the clause number,
          instead of taking an argument.

               (format #f "~2[peach~;banana~;mango~]") ⇒ "mango"

          If the clause number is out of range then nothing is output.
          Or the last clause can be ~:; to use that for a number out of
          range.

               (format #f "~[banana~;mango~]"         99) ⇒ ""
               (format #f "~[banana~;mango~:;fruit~]" 99) ⇒ "fruit"

          ~:[ treats the argument as a flag, and expects two clauses.
          The first is used if the argument is ‘#f’ or the second
          otherwise.

               (format #f "~:[false~;not false~]" #f)   ⇒ "false"
               (format #f "~:[false~;not false~]" 'abc) ⇒ "not false"

               (let ((n 3))
                 (format #t "~d gnu~:[s are~; is~] here" n (= 1 n)))
               ⊣ 3 gnus are here

          ~@[ also treats the argument as a flag, and expects one
          clause.  If the argument is ‘#f’ then no output is produced
          and the argument is consumed, otherwise the clause is used and
          the argument is not consumed, it’s left for the clause.  This
          can be used for instance to suppress output if ‘#f’ means
          something not available.

               (format #f "~@[temperature=~d~]" 27) ⇒ "temperature=27"
               (format #f "~@[temperature=~d~]" #f) ⇒ ""

     ~^
          Escape.  Parameters: VAL1, VAL2, VAL3.

          Stop formatting if there are no more arguments.  This can be
          used for instance to have a format string adapt to a variable
          number of arguments.

               (format #t "~d~^ ~d" 1)   ⊣ 1
               (format #t "~d~^ ~d" 1 2) ⊣ 1 2

          Within a ~{ ~} iteration, ~^ stops the current iteration step
          if there are no more arguments to that step, but continuing
          with possible further steps and the rest of the format.  This
          can be used for instance to avoid a separator on the last
          iteration, or to adapt to variable length argument lists.

               (format #f "~{~d~^/~} go"    '(1 2 3))     ⇒ "1/2/3 go"
               (format #f "~:{ ~d~^~d~} go" '((1) (2 3))) ⇒ " 1 23 go"

          Within a ~?  sub-format, ~^ operates just on that sub-format.
          If it terminates the sub-format then the originating format
          will still continue.

               (format #t "~? items" "~d~^ ~d" '(1))   ⊣ 1 items
               (format #t "~? items" "~d~^ ~d" '(1 2)) ⊣ 1 2 items

          The parameters to ~^ (which are numbers) change the condition
          used to terminate.  For a single parameter, termination is
          when that value is zero (notice this makes plain ~^ equivalent
          to ~#^).  For two parameters, termination is when those two
          are equal.  For three parameters, termination is when VAL1 <=
          VAL2 and VAL2 <= VAL3.

     ~q
          Inquiry message.  Insert a copyright message into the output.

          ~:q inserts the format implementation version.


     It’s an error if there are not enough arguments for the escapes in
     the format string, but any excess arguments are ignored.

     Iterations ~{ ~} and conditionals ~[ ~; ~] can be nested, but must
     be properly nested, meaning the inner form must be entirely within
     the outer form.  So it’s not possible, for instance, to try to
     conditionalize the endpoint of an iteration.

          (format #t "~{ ~[ ... ~] ~}" ...)       ;; good
          (format #t "~{ ~[ ... ~} ... ~]" ...)   ;; bad

     The same applies to case conversions ~( ~), they must properly nest
     with respect to iterations and conditionals (though currently a
     case conversion cannot nest within another case conversion).

     When a sub-format (~?)  is used, that sub-format string must be
     self-contained.  It cannot for instance give a ~{ to begin an
     iteration form and have the ~} up in the originating format, or
     similar.


   Guile contains a ‘format’ procedure even when the module ‘(ice-9
format)’ is not loaded.  The default ‘format’ is ‘simple-format’ (*note
Writing::), it doesn’t support all escape sequences documented in this
section, and will signal an error if you try to use one of them.  The
reason for two versions is that the full ‘format’ is fairly large and
requires some time to load.  ‘simple-format’ is often adequate too.

   ---------- Footnotes ----------

   (1) The ~h format specifier first appeared in Guile version 2.0.6.


File: guile.info,  Node: File Tree Walk,  Next: Queues,  Prev: Formatted Output,  Up: Guile Modules

7.11 File Tree Walk
===================

The functions in this section traverse a tree of files and directories.
They come in two flavors: the first one is a high-level functional
interface, and the second one is similar to the C ‘ftw’ and ‘nftw’
routines (*note (libc)Working with Directory Trees::).

     (use-modules (ice-9 ftw))

 -- Scheme Procedure: file-system-tree file-name [enter? [stat]]
     Return a tree of the form ‘(FILE-NAME STAT CHILDREN ...)’ where
     STAT is the result of ‘(STAT FILE-NAME)’ and CHILDREN are similar
     structures for each file contained in FILE-NAME when it designates
     a directory.

     The optional ENTER? predicate is invoked as ‘(ENTER? NAME STAT)’
     and should return true to allow recursion into directory NAME; the
     default value is a procedure that always returns ‘#t’.  When a
     directory does not match ENTER?, it nonetheless appears in the
     resulting tree, only with zero children.

     The STAT argument is optional and defaults to ‘lstat’, as for
     ‘file-system-fold’ (see below.)

     The example below shows how to obtain a hierarchical listing of the
     files under the ‘module/language’ directory in the Guile source
     tree, discarding their ‘stat’ info:

          (use-modules (ice-9 match))

          (define remove-stat
            ;; Remove the `stat' object the `file-system-tree' provides
            ;; for each file in the tree.
            (match-lambda
              ((name stat)              ; flat file
               name)
              ((name stat children ...) ; directory
               (list name (map remove-stat children)))))

          (let ((dir (string-append (assq-ref %guile-build-info 'top_srcdir)
                                    "/module/language")))
            (remove-stat (file-system-tree dir)))

          ⇒
          ("language"
           (("value" ("spec.go" "spec.scm"))
            ("scheme"
             ("spec.go"
              "spec.scm"
              "compile-tree-il.scm"
              "decompile-tree-il.scm"
              "decompile-tree-il.go"
              "compile-tree-il.go"))
            ("tree-il"
             ("spec.go"
              "fix-letrec.go"
              "inline.go"
              "fix-letrec.scm"
              "compile-glil.go"
              "spec.scm"
              "optimize.scm"
              "primitives.scm"
              …))
            …))

   It is often desirable to process directories entries directly, rather
than building up a tree of entries in memory, like ‘file-system-tree’
does.  The following procedure, a "combinator", is designed to allow
directory entries to be processed directly as a directory tree is
traversed; in fact, ‘file-system-tree’ is implemented in terms of it.

 -- Scheme Procedure: file-system-fold enter? leaf down up skip error
          init file-name [stat]
     Traverse the directory at FILE-NAME, recursively, and return the
     result of the successive applications of the LEAF, DOWN, UP, and
     SKIP procedures as described below.

     Enter sub-directories only when ‘(ENTER? PATH STAT RESULT)’ returns
     true.  When a sub-directory is entered, call ‘(DOWN PATH STAT
     RESULT)’, where PATH is the path of the sub-directory and STAT the
     result of ‘(false-if-exception (STAT PATH))’; when it is left, call
     ‘(UP PATH STAT RESULT)’.

     For each file in a directory, call ‘(LEAF PATH STAT RESULT)’.

     When ENTER? returns ‘#f’, or when an unreadable directory is
     encountered, call ‘(SKIP PATH STAT RESULT)’.

     When FILE-NAME names a flat file, ‘(LEAF PATH STAT INIT)’ is
     returned.

     When an ‘opendir’ or STAT call fails, call ‘(ERROR PATH STAT ERRNO
     RESULT)’, with ERRNO being the operating system error number that
     was raised—e.g., ‘EACCES’—and STAT either ‘#f’ or the result of the
     STAT call for that entry, when available.

     The special ‘.’ and ‘..’ entries are not passed to these
     procedures.  The PATH argument to the procedures is a full file
     name—e.g., ‘"../foo/bar/gnu"’; if FILE-NAME is an absolute file
     name, then PATH is also an absolute file name.  Files and
     directories, as identified by their device/inode number pair, are
     traversed only once.

     The optional STAT argument defaults to ‘lstat’, which means that
     symbolic links are not followed; the ‘stat’ procedure can be used
     instead when symbolic links are to be followed (*note stat: File
     System.).

     The example below illustrates the use of ‘file-system-fold’:

          (define (total-file-size file-name)
            "Return the size in bytes of the files under FILE-NAME (similar
          to `du --apparent-size' with GNU Coreutils.)"

            (define (enter? name stat result)
              ;; Skip version control directories.
              (not (member (basename name) '(".git" ".svn" "CVS"))))
            (define (leaf name stat result)
              ;; Return RESULT plus the size of the file at NAME.
              (+ result (stat:size stat)))

            ;; Count zero bytes for directories.
            (define (down name stat result) result)
            (define (up name stat result) result)

            ;; Likewise for skipped directories.
            (define (skip name stat result) result)

            ;; Ignore unreadable files/directories but warn the user.
            (define (error name stat errno result)
              (format (current-error-port) "warning: ~a: ~a~%"
                      name (strerror errno))
              result)

            (file-system-fold enter? leaf down up skip error
                                     0  ; initial counter is zero bytes
                                     file-name))

          (total-file-size ".")
          ⇒ 8217554

          (total-file-size "/dev/null")
          ⇒ 0

   The alternative C-like functions are described below.

 -- Scheme Procedure: scandir name [select? [entry<?]]
     Return the list of the names of files contained in directory NAME
     that match predicate SELECT? (by default, all files).  The returned
     list of file names is sorted according to ENTRY<?, which defaults
     to ‘string-locale<?’ such that file names are sorted in the
     locale’s alphabetical order (*note Text Collation::).  Return ‘#f’
     when NAME is unreadable or is not a directory.

     This procedure is modeled after the C library function of the same
     name (*note (libc)Scanning Directory Content::).

 -- Scheme Procedure: ftw startname proc ['hash-size n]
     Walk the file system tree descending from STARTNAME, calling PROC
     for each file and directory.

     Hard links and symbolic links are followed.  A file or directory is
     reported to PROC only once, and skipped if seen again in another
     place.  One consequence of this is that ‘ftw’ is safe against
     circularly linked directory structures.

     Each PROC call is ‘(PROC filename statinfo flag)’ and it should
     return ‘#t’ to continue, or any other value to stop.

     FILENAME is the item visited, being STARTNAME plus a further path
     and the name of the item.  STATINFO is the return from ‘stat’
     (*note File System::) on FILENAME.  FLAG is one of the following
     symbols,

     ‘regular’
          FILENAME is a file, this includes special files like devices,
          named pipes, etc.

     ‘directory’
          FILENAME is a directory.

     ‘invalid-stat’
          An error occurred when calling ‘stat’, so nothing is known.
          STATINFO is ‘#f’ in this case.

     ‘directory-not-readable’
          FILENAME is a directory, but one which cannot be read and
          hence won’t be recursed into.

     ‘symlink’
          FILENAME is a dangling symbolic link.  Symbolic links are
          normally followed and their target reported, the link itself
          is reported if the target does not exist.

     The return value from ‘ftw’ is ‘#t’ if it ran to completion, or
     otherwise the non-‘#t’ value from PROC which caused the stop.

     Optional argument symbol ‘hash-size’ and an integer can be given to
     set the size of the hash table used to track items already visited.
     (*note Hash Table Reference::)

     In the current implementation, returning non-‘#t’ from PROC is the
     only valid way to terminate ‘ftw’.  PROC must not use ‘throw’ or
     similar to escape.

 -- Scheme Procedure: nftw startname proc ['chdir] ['depth] ['hash-size
          n] ['mount] ['physical]
     Walk the file system tree starting at STARTNAME, calling PROC for
     each file and directory.  ‘nftw’ has extra features over the basic
     ‘ftw’ described above.

     Like ‘ftw’, hard links and symbolic links are followed.  A file or
     directory is reported to PROC only once, and skipped if seen again
     in another place.  One consequence of this is that ‘nftw’ is safe
     against circular linked directory structures.

     Each PROC call is ‘(PROC filename statinfo flag base level)’ and it
     should return ‘#t’ to continue, or any other value to stop.

     FILENAME is the item visited, being STARTNAME plus a further path
     and the name of the item.  STATINFO is the return from ‘stat’ on
     FILENAME (*note File System::).  BASE is an integer offset into
     FILENAME which is where the basename for this item begins.  LEVEL
     is an integer giving the directory nesting level, starting from 0
     for the contents of STARTNAME (or that item itself if it’s a file).
     FLAG is one of the following symbols,

     ‘regular’
          FILENAME is a file, including special files like devices,
          named pipes, etc.

     ‘directory’
          FILENAME is a directory.

     ‘directory-processed’
          FILENAME is a directory, and its contents have all been
          visited.  This flag is given instead of ‘directory’ when the
          ‘depth’ option below is used.

     ‘invalid-stat’
          An error occurred when applying ‘stat’ to FILENAME, so nothing
          is known about it.  STATINFO is ‘#f’ in this case.

     ‘directory-not-readable’
          FILENAME is a directory, but one which cannot be read and
          hence won’t be recursed into.

     ‘stale-symlink’
          FILENAME is a dangling symbolic link.  Links are normally
          followed and their target reported, the link itself is
          reported if its target does not exist.

     ‘symlink’
          When the ‘physical’ option described below is used, this
          indicates FILENAME is a symbolic link whose target exists (and
          is not being followed).

     The following optional arguments can be given to modify the way
     ‘nftw’ works.  Each is passed as a symbol (and ‘hash-size’ takes a
     following integer value).

     ‘chdir’
          Change to the directory containing the item before calling
          PROC.  When ‘nftw’ returns the original current directory is
          restored.

          Under this option, generally the BASE parameter to each PROC
          call should be used to pick out the base part of the FILENAME.
          The FILENAME is still a path but with a changed directory it
          won’t be valid (unless the STARTNAME directory was absolute).

     ‘depth’
          Visit files “depth first”, meaning PROC is called for the
          contents of each directory before it’s called for the
          directory itself.  Normally a directory is reported first,
          then its contents.

          Under this option, the FLAG to PROC for a directory is
          ‘directory-processed’ instead of ‘directory’.

     ‘hash-size N’
          Set the size of the hash table used to track items already
          visited.  (*note Hash Table Reference::)

     ‘mount’
          Don’t cross a mount point, meaning only visit items on the
          same file system as STARTNAME (ie. the same ‘stat:dev’).

     ‘physical’
          Don’t follow symbolic links, instead report them to PROC as
          ‘symlink’.  Dangling links (those whose target doesn’t exist)
          are still reported as ‘stale-symlink’.

     The return value from ‘nftw’ is ‘#t’ if it ran to completion, or
     otherwise the non-‘#t’ value from PROC which caused the stop.

     In the current implementation, returning non-‘#t’ from PROC is the
     only valid way to terminate ‘ftw’.  PROC must not use ‘throw’ or
     similar to escape.


File: guile.info,  Node: Queues,  Next: Streams,  Prev: File Tree Walk,  Up: Guile Modules

7.12 Queues
===========

The functions in this section are provided by

     (use-modules (ice-9 q))

   This module implements queues holding arbitrary scheme objects and
designed for efficient first-in / first-out operations.

   ‘make-q’ creates a queue, and objects are entered and removed with
‘enq!’ and ‘deq!’.  ‘q-push!’ and ‘q-pop!’ can be used too, treating the
front of the queue like a stack.


 -- Scheme Procedure: make-q
     Return a new queue.

 -- Scheme Procedure: q? obj
     Return ‘#t’ if OBJ is a queue, or ‘#f’ if not.

     Note that queues are not a distinct class of objects but are
     implemented with cons cells.  For that reason certain list
     structures can get ‘#t’ from ‘q?’.

 -- Scheme Procedure: enq! q obj
     Add OBJ to the rear of Q, and return Q.

 -- Scheme Procedure: deq! q
 -- Scheme Procedure: q-pop! q
     Remove and return the front element from Q.  If Q is empty, a
     ‘q-empty’ exception is thrown.

     ‘deq!’ and ‘q-pop!’ are the same operation, the two names just let
     an application match ‘enq!’ with ‘deq!’, or ‘q-push!’ with
     ‘q-pop!’.

 -- Scheme Procedure: q-push! q obj
     Add OBJ to the front of Q, and return Q.

 -- Scheme Procedure: q-length q
     Return the number of elements in Q.

 -- Scheme Procedure: q-empty? q
     Return true if Q is empty.

 -- Scheme Procedure: q-empty-check q
     Throw a ‘q-empty’ exception if Q is empty.

 -- Scheme Procedure: q-front q
     Return the first element of Q (without removing it).  If Q is
     empty, a ‘q-empty’ exception is thrown.

 -- Scheme Procedure: q-rear q
     Return the last element of Q (without removing it).  If Q is empty,
     a ‘q-empty’ exception is thrown.

 -- Scheme Procedure: q-remove! q obj
     Remove all occurrences of OBJ from Q, and return Q.  OBJ is
     compared to queue elements using ‘eq?’.


   The ‘q-empty’ exceptions described above are thrown just as ‘(throw
'q-empty)’, there’s no message etc like an error throw.

   A queue is implemented as a cons cell, the ‘car’ containing a list of
queued elements, and the ‘cdr’ being the last cell in that list (for
ease of enqueuing).

     (LIST . LAST-CELL)

If the queue is empty, LIST is the empty list and LAST-CELL is ‘#f’.

   An application can directly access the queue list if desired, for
instance to search the elements or to insert at a specific point.

 -- Scheme Procedure: sync-q! q
     Recompute the LAST-CELL field in Q.

     All the operations above maintain LAST-CELL as described, so
     normally there’s no need for ‘sync-q!’.  But if an application
     modifies the queue LIST then it must either maintain LAST-CELL
     similarly, or call ‘sync-q!’ to recompute it.


File: guile.info,  Node: Streams,  Next: Buffered Input,  Prev: Queues,  Up: Guile Modules

7.13 Streams
============

This section documents Guile’s legacy stream module.  For a more
complete and portable stream library, *note SRFI-41::.

   A stream represents a sequence of values, each of which is calculated
only when required.  This allows large or even infinite sequences to be
represented and manipulated with familiar operations like “car”, “cdr”,
“map” or “fold”.  In such manipulations only as much as needed is
actually held in memory at any one time.  The functions in this section
are available from

     (use-modules (ice-9 streams))

   Streams are implemented using promises (*note Delayed Evaluation::),
which is how the underlying calculation of values is made only when
needed, and the values then retained so the calculation is not repeated.

Here is a simple example producing a stream of all odd numbers,

     (define odds (make-stream (lambda (state)
                                 (cons state (+ state 2)))
                               1))
     (stream-car odds)              ⇒ 1
     (stream-car (stream-cdr odds)) ⇒ 3

‘stream-map’ could be used to derive a stream of odd squares,

     (define (square n) (* n n))
     (define oddsquares (stream-map square odds))

   These are infinite sequences, so it’s not possible to convert them to
a list, but they could be printed (infinitely) with for example

     (stream-for-each (lambda (n sq)
                        (format #t "~a squared is ~a\n" n sq))
                      odds oddsquares)
     ⊣
     1 squared is 1
     3 squared is 9
     5 squared is 25
     7 squared is 49
     …


 -- Scheme Procedure: make-stream proc initial-state
     Return a new stream, formed by calling PROC successively.

     Each call is ‘(PROC STATE)’, it should return a pair, the ‘car’
     being the value for the stream, and the ‘cdr’ being the new STATE
     for the next call.  For the first call STATE is the given
     INITIAL-STATE.  At the end of the stream, PROC should return some
     non-pair object.

 -- Scheme Procedure: stream-car stream
     Return the first element from STREAM.  STREAM must not be empty.

 -- Scheme Procedure: stream-cdr stream
     Return a stream which is the second and subsequent elements of
     STREAM.  STREAM must not be empty.

 -- Scheme Procedure: stream-null? stream
     Return true if STREAM is empty.

 -- Scheme Procedure: list->stream list
 -- Scheme Procedure: vector->stream vector
     Return a stream with the contents of LIST or VECTOR.

     LIST or VECTOR should not be modified subsequently, since it’s
     unspecified whether changes there will be reflected in the stream
     returned.

 -- Scheme Procedure: port->stream port readproc
     Return a stream which is the values obtained by reading from PORT
     using READPROC.  Each read call is ‘(READPROC PORT)’, and it should
     return an EOF object (*note Reading::) at the end of input.

     For example a stream of characters from a file,

          (port->stream (open-input-file "/foo/bar.txt") read-char)

 -- Scheme Procedure: stream->list stream
     Return a list which is the entire contents of STREAM.

 -- Scheme Procedure: stream->reversed-list stream
     Return a list which is the entire contents of STREAM, but in
     reverse order.

 -- Scheme Procedure: stream->list&length stream
     Return two values (*note Multiple Values::), being firstly a list
     which is the entire contents of STREAM, and secondly the number of
     elements in that list.

 -- Scheme Procedure: stream->reversed-list&length stream
     Return two values (*note Multiple Values::) being firstly a list
     which is the entire contents of STREAM, but in reverse order, and
     secondly the number of elements in that list.

 -- Scheme Procedure: stream->vector stream
     Return a vector which is the entire contents of STREAM.

 -- Function: stream-fold proc init stream1 stream2 …
     Apply PROC successively over the elements of the given streams,
     from first to last until the end of the shortest stream is reached.
     Return the result from the last PROC call.

     Each call is ‘(PROC elem1 elem2 … prev)’, where each ELEM is from
     the corresponding STREAM.  PREV is the return from the previous
     PROC call, or the given INIT for the first call.

 -- Function: stream-for-each proc stream1 stream2 …
     Call PROC on the elements from the given STREAMs.  The return value
     is unspecified.

     Each call is ‘(PROC elem1 elem2 …)’, where each ELEM is from the
     corresponding STREAM.  ‘stream-for-each’ stops when it reaches the
     end of the shortest STREAM.

 -- Function: stream-map proc stream1 stream2 …
     Return a new stream which is the results of applying PROC to the
     elements of the given STREAMs.

     Each call is ‘(PROC elem1 elem2 …)’, where each ELEM is from the
     corresponding STREAM.  The new stream ends when the end of the
     shortest given STREAM is reached.


File: guile.info,  Node: Buffered Input,  Next: Expect,  Prev: Streams,  Up: Guile Modules

7.14 Buffered Input
===================

The following functions are provided by

     (use-modules (ice-9 buffered-input))

   A buffered input port allows a reader function to return chunks of
characters which are to be handed out on reading the port.  A notion of
further input for an application level logical expression is maintained
too, and passed through to the reader.

 -- Scheme Procedure: make-buffered-input-port reader
     Create an input port which returns characters obtained from the
     given READER function.  READER is called (READER cont), and should
     return a string or an EOF object.

     The new port gives precisely the characters returned by READER,
     nothing is added, so if any newline characters or other separators
     are desired they must come from the reader function.

     The CONT parameter to READER is ‘#f’ for initial input, or ‘#t’
     when continuing an expression.  This is an application level
     notion, set with ‘set-buffered-input-continuation?!’ below.  If the
     user has entered a partial expression then it allows READER for
     instance to give a different prompt to show more is required.

 -- Scheme Procedure: make-line-buffered-input-port reader
     Create an input port which returns characters obtained from the
     specified READER function, similar to ‘make-buffered-input-port’
     above, but where READER is expected to be a line-oriented.

     READER is called (READER cont), and should return a string or an
     EOF object as above.  Each string is a line of input without a
     newline character, the port code inserts a newline after each
     string.

 -- Scheme Procedure: set-buffered-input-continuation?! port cont
     Set the input continuation flag for a given buffered input PORT.

     An application uses this by calling with a CONT flag of ‘#f’ when
     beginning to read a new logical expression.  For example with the
     Scheme ‘read’ function (*note Scheme Read::),

          (define my-port (make-buffered-input-port my-reader))

          (set-buffered-input-continuation?! my-port #f)
          (let ((obj (read my-port)))
            ...


File: guile.info,  Node: Expect,  Next: sxml-match,  Prev: Buffered Input,  Up: Guile Modules

7.15 Expect
===========

The macros in this section are made available with:

     (use-modules (ice-9 expect))

   ‘expect’ is a macro for selecting actions based on the output from a
port.  The name comes from a tool of similar functionality by Don Libes.
Actions can be taken when a particular string is matched, when a timeout
occurs, or when end-of-file is seen on the port.  The ‘expect’ macro is
described below; ‘expect-strings’ is a front-end to ‘expect’ based on
regexec (see the regular expression documentation).

 -- Macro: expect-strings clause …
     By default, ‘expect-strings’ will read from the current input port.
     The first term in each clause consists of an expression evaluating
     to a string pattern (regular expression).  As characters are read
     one-by-one from the port, they are accumulated in a buffer string
     which is matched against each of the patterns.  When a pattern
     matches, the remaining expression(s) in the clause are evaluated
     and the value of the last is returned.  For example:

          (with-input-from-file "/etc/passwd"
            (lambda ()
              (expect-strings
                ("^nobody" (display "Got a nobody user.\n")
                           (display "That's no problem.\n"))
                ("^daemon" (display "Got a daemon user.\n")))))

     The regular expression is compiled with the ‘REG_NEWLINE’ flag, so
     that the ^ and $ anchors will match at any newline, not just at the
     start and end of the string.

     There are two other ways to write a clause:

     The expression(s) to evaluate can be omitted, in which case the
     result of the regular expression match (converted to strings, as
     obtained from regexec with match-pick set to "") will be returned
     if the pattern matches.

     The symbol ‘=>’ can be used to indicate that the expression is a
     procedure which will accept the result of a successful regular
     expression match.  E.g.,

          ("^daemon" => write)
          ("^d(aemon)" => (lambda args (for-each write args)))
          ("^da(em)on" => (lambda (all sub)
                            (write all) (newline)
                            (write sub) (newline)))

     The order of the substrings corresponds to the order in which the
     opening brackets occur.

     A number of variables can be used to control the behaviour of
     ‘expect’ (and ‘expect-strings’).  Most have default top-level
     bindings to the value ‘#f’, which produces the default behaviour.
     They can be redefined at the top level or locally bound in a form
     enclosing the expect expression.

     ‘expect-port’
          A port to read characters from, instead of the current input
          port.
     ‘expect-timeout’
          ‘expect’ will terminate after this number of seconds,
          returning ‘#f’ or the value returned by expect-timeout-proc.
     ‘expect-timeout-proc’
          A procedure called if timeout occurs.  The procedure takes a
          single argument: the accumulated string.
     ‘expect-eof-proc’
          A procedure called if end-of-file is detected on the input
          port.  The procedure takes a single argument: the accumulated
          string.
     ‘expect-char-proc’
          A procedure to be called every time a character is read from
          the port.  The procedure takes a single argument: the
          character which was read.
     ‘expect-strings-compile-flags’
          Flags to be used when compiling a regular expression, which
          are passed to ‘make-regexp’ *Note Regexp Functions::.  The
          default value is ‘regexp/newline’.
     ‘expect-strings-exec-flags’
          Flags to be used when executing a regular expression, which
          are passed to regexp-exec *Note Regexp Functions::.  The
          default value is ‘regexp/noteol’, which prevents ‘$’ from
          matching the end of the string while it is still accumulating,
          but still allows it to match after a line break or at the end
          of file.

     Here’s an example using all of the variables:

          (let ((expect-port (open-input-file "/etc/passwd"))
                (expect-timeout 1)
                (expect-timeout-proc
                  (lambda (s) (display "Times up!\n")))
                (expect-eof-proc
                  (lambda (s) (display "Reached the end of the file!\n")))
                (expect-char-proc display)
                (expect-strings-compile-flags (logior regexp/newline regexp/icase))
                (expect-strings-exec-flags 0))
             (expect-strings
               ("^nobody"  (display "Got a nobody user\n"))))

 -- Macro: expect clause …
     ‘expect’ is used in the same way as ‘expect-strings’, but tests are
     specified not as patterns, but as procedures.  The procedures are
     called in turn after each character is read from the port, with two
     arguments: the value of the accumulated string and a flag to
     indicate whether end-of-file has been reached.  The flag will
     usually be ‘#f’, but if end-of-file is reached, the procedures are
     called an additional time with the final accumulated string and
     ‘#t’.

     The test is successful if the procedure returns a non-false value.

     If the ‘=>’ syntax is used, then if the test succeeds it must
     return a list containing the arguments to be provided to the
     corresponding expression.

     In the following example, a string will only be matched at the
     beginning of the file:

          (let ((expect-port (open-input-file "/etc/passwd")))
            (expect
               ((lambda (s eof?) (string=? s "fnord!"))
                  (display "Got a nobody user!\n"))))

     The control variables described for ‘expect-strings’ also influence
     the behaviour of ‘expect’, with the exception of variables whose
     names begin with ‘expect-strings-’.


File: guile.info,  Node: sxml-match,  Next: The Scheme shell (scsh),  Prev: Expect,  Up: Guile Modules

7.16 ‘sxml-match’: Pattern Matching of SXML
===========================================

The ‘(sxml match)’ module provides syntactic forms for pattern matching
of SXML trees, in a “by example” style reminiscent of the pattern
matching of the ‘syntax-rules’ and ‘syntax-case’ macro systems.  *Note
SXML::, for more information on SXML.

   The following example(1) provides a brief illustration, transforming
a music album catalog language into HTML.

     (define (album->html x)
       (sxml-match x
         [(album (@ (title ,t)) (catalog (num ,n) (fmt ,f)) ...)
          `(ul (li ,t)
               (li (b ,n) (i ,f)) ...)]))

   Three macros are provided: ‘sxml-match’, ‘sxml-match-let’, and
‘sxml-match-let*’.

   Compared to a standard s-expression pattern matcher (*note Pattern
Matching::), ‘sxml-match’ provides the following benefits:

   • matching of SXML elements does not depend on any degree of
     normalization of the SXML;
   • matching of SXML attributes (within an element) is under-ordered;
     the order of the attributes specified within the pattern need not
     match the ordering with the element being matched;
   • all attributes specified in the pattern must be present in the
     element being matched; in the spirit that XML is ’extensible’, the
     element being matched may include additional attributes not
     specified in the pattern.

   The present module is a descendant of WebIt!, and was inspired by an
s-expression pattern matcher developed by Erik Hilsdale, Dan Friedman,
and Kent Dybvig at Indiana University.

Syntax
------

‘sxml-match’ provides ‘case’-like form for pattern matching of XML
nodes.

 -- Scheme Syntax: sxml-match input-expression clause1 clause2 …
     Match INPUT-EXPRESSION, an SXML tree, according to the given
     CLAUSEs (one or more), each consisting of a pattern and one or more
     expressions to be evaluated if the pattern match succeeds.
     Optionally, each CLAUSE within ‘sxml-match’ may include a "guard
     expression".

   The pattern notation is based on that of Scheme’s ‘syntax-rules’ and
‘syntax-case’ macro systems.  The grammar for the ‘sxml-match’ syntax is
given below:

match-form ::= (sxml-match input-expression
                 clause+)

clause ::= [node-pattern action-expression+]
         | [node-pattern (guard expression*) action-expression+]

node-pattern ::= literal-pattern
               | pat-var-or-cata
               | element-pattern
               | list-pattern

literal-pattern ::= string
                  | character
                  | number
                  | #t
                  | #f

attr-list-pattern ::= (@ attribute-pattern*)
                    | (@ attribute-pattern* . pat-var-or-cata)

attribute-pattern ::= (tag-symbol attr-val-pattern)

attr-val-pattern ::= literal-pattern
                   | pat-var-or-cata
                   | (pat-var-or-cata default-value-expr)

element-pattern ::= (tag-symbol attr-list-pattern?)
                  | (tag-symbol attr-list-pattern? nodeset-pattern)
                  | (tag-symbol attr-list-pattern?
                                nodeset-pattern? . pat-var-or-cata)

list-pattern ::= (list nodeset-pattern)
               | (list nodeset-pattern? . pat-var-or-cata)
               | (list)

nodeset-pattern ::= node-pattern
                  | node-pattern ...
                  | node-pattern nodeset-pattern
                  | node-pattern ... nodeset-pattern

pat-var-or-cata ::= (unquote var-symbol)
                  | (unquote [var-symbol*])
                  | (unquote [cata-expression -> var-symbol*])

   Within a list or element body pattern, ellipses may appear only once,
but may be followed by zero or more node patterns.

   Guard expressions cannot refer to the return values of catamorphisms.

   Ellipses in the output expressions must appear only in an expression
context; ellipses are not allowed in a syntactic form.

   The sections below illustrate specific aspects of the ‘sxml-match’
pattern matcher.

Matching XML Elements
---------------------

The example below illustrates the pattern matching of an XML element:

     (sxml-match '(e (@ (i 1)) 3 4 5)
       [(e (@ (i ,d)) ,a ,b ,c) (list d a b c)]
       [,otherwise #f])

   Each clause in ‘sxml-match’ contains two parts: a pattern and one or
more expressions which are evaluated if the pattern is successfully
match.  The example above matches an element ‘e’ with an attribute ‘i’
and three children.

   Pattern variables are must be “unquoted” in the pattern.  The above
expression binds D to ‘1’, A to ‘3’, B to ‘4’, and C to ‘5’.

Ellipses in Patterns
--------------------

As in ‘syntax-rules’, ellipses may be used to specify a repeated
pattern.  Note that the pattern ‘item ...’ specifies zero-or-more
matches of the pattern ‘item’.

   The use of ellipses in a pattern is illustrated in the code fragment
below, where nested ellipses are used to match the children of repeated
instances of an ‘a’ element, within an element ‘d’.

     (define x '(d (a 1 2 3) (a 4 5) (a 6 7 8) (a 9 10)))

     (sxml-match x
       [(d (a ,b ...) ...)
        (list (list b ...) ...)])

   The above expression returns a value of ‘((1 2 3) (4 5) (6 7 8) (9
10))’.

Ellipses in Quasiquote’d Output
-------------------------------

Within the body of an ‘sxml-match’ form, a slightly extended version of
quasiquote is provided, which allows the use of ellipses.  This is
illustrated in the example below.

     (sxml-match '(e 3 4 5 6 7)
       [(e ,i ... 6 7) `("start" ,(list 'wrap i) ... "end")]
       [,otherwise #f])

   The general pattern is that ‘`(something ,i ...)’ is rewritten as
‘`(something ,@i)’.

Matching Nodesets
-----------------

A nodeset pattern is designated by a list in the pattern, beginning the
identifier list.  The example below illustrates matching a nodeset.

     (sxml-match '("i" "j" "k" "l" "m")
       [(list ,a ,b ,c ,d ,e)
        `((p ,a) (p ,b) (p ,c) (p ,d) (p ,e))])

   This example wraps each nodeset item in an HTML paragraph element.
This example can be rewritten and simplified through using ellipsis:

     (sxml-match '("i" "j" "k" "l" "m")
       [(list ,i ...)
        `((p ,i) ...)])

   This version will match nodesets of any length, and wrap each item in
the nodeset in an HTML paragraph element.

Matching the “Rest” of a Nodeset
--------------------------------

Matching the “rest” of a nodeset is achieved by using a ‘. rest)’
pattern at the end of an element or nodeset pattern.

   This is illustrated in the example below:

     (sxml-match '(e 3 (f 4 5 6) 7)
       [(e ,a (f . ,y) ,d)
        (list a y d)])

   The above expression returns ‘(3 (4 5 6) 7)’.

Matching the Unmatched Attributes
---------------------------------

Sometimes it is useful to bind a list of attributes present in the
element being matched, but which do not appear in the pattern.  This is
achieved by using a ‘. rest)’ pattern at the end of the attribute list
pattern.  This is illustrated in the example below:

     (sxml-match '(a (@ (z 1) (y 2) (x 3)) 4 5 6)
       [(a (@ (y ,www) . ,qqq) ,t ,u ,v)
        (list www qqq t u v)])

   The above expression matches the attribute ‘y’ and binds a list of
the remaining attributes to the variable QQQ.  The result of the above
expression is ‘(2 ((z 1) (x 3)) 4 5 6)’.

   This type of pattern also allows the binding of all attributes:

     (sxml-match '(a (@ (z 1) (y 2) (x 3)))
       [(a (@ . ,qqq))
        qqq])

Default Values in Attribute Patterns
------------------------------------

It is possible to specify a default value for an attribute which is used
if the attribute is not present in the element being matched.  This is
illustrated in the following example:

     (sxml-match '(e 3 4 5)
       [(e (@ (z (,d 1))) ,a ,b ,c) (list d a b c)])

   The value ‘1’ is used when the attribute ‘z’ is absent from the
element ‘e’.

Guards in Patterns
------------------

Guards may be added to a pattern clause via the ‘guard’ keyword.  A
guard expression may include zero or more expressions which are
evaluated only if the pattern is matched.  The body of the clause is
only evaluated if the guard expressions evaluate to ‘#t’.

   The use of guard expressions is illustrated below:

     (sxml-match '(a 2 3)
       ((a ,n) (guard (number? n)) n)
       ((a ,m ,n) (guard (number? m) (number? n)) (+ m n)))

Catamorphisms
-------------

The example below illustrates the use of explicit recursion within an
‘sxml-match’ form.  This example implements a simple calculator for the
basic arithmetic operations, which are represented by the XML elements
‘plus’, ‘minus’, ‘times’, and ‘div’.

     (define simple-eval
       (lambda (x)
         (sxml-match x
           [,i (guard (integer? i)) i]
           [(plus ,x ,y) (+ (simple-eval x) (simple-eval y))]
           [(times ,x ,y) (* (simple-eval x) (simple-eval y))]
           [(minus ,x ,y) (- (simple-eval x) (simple-eval y))]
           [(div ,x ,y) (/ (simple-eval x) (simple-eval y))]
           [,otherwise (error "simple-eval: invalid expression" x)])))

   Using the catamorphism feature of ‘sxml-match’, a more concise
version of ‘simple-eval’ can be written.  The pattern ‘,[x]’ recursively
invokes the pattern matcher on the value bound in this position.

     (define simple-eval
       (lambda (x)
         (sxml-match x
           [,i (guard (integer? i)) i]
           [(plus ,[x] ,[y]) (+ x y)]
           [(times ,[x] ,[y]) (* x y)]
           [(minus ,[x] ,[y]) (- x y)]
           [(div ,[x] ,[y]) (/ x y)]
           [,otherwise (error "simple-eval: invalid expression" x)])))

Named-Catamorphisms
-------------------

It is also possible to explicitly name the operator in the “cata”
position.  Where ‘,[id*]’ recurs to the top of the current ‘sxml-match’,
‘,[cata -> id*]’ recurs to ‘cata’.  ‘cata’ must evaluate to a procedure
which takes one argument, and returns as many values as there are
identifiers following ‘->’.

   Named catamorphism patterns allow processing to be split into
multiple, mutually recursive procedures.  This is illustrated in the
example below: a transformation that formats a “TV Guide” into HTML.

     (define (tv-guide->html g)
       (define (cast-list cl)
         (sxml-match cl
           [(CastList (CastMember (Character (Name ,ch)) (Actor (Name ,a))) ...)
            `(div (ul (li ,ch ": " ,a) ...))]))
       (define (prog p)
         (sxml-match p
           [(Program (Start ,start-time) (Duration ,dur) (Series ,series-title)
                     (Description ,desc ...))
            `(div (p ,start-time
                     (br) ,series-title
                     (br) ,desc ...))]
           [(Program (Start ,start-time) (Duration ,dur) (Series ,series-title)
                     (Description ,desc ...)
                     ,[cast-list -> cl])
            `(div (p ,start-time
                     (br) ,series-title
                     (br) ,desc ...)
                  ,cl)]))
       (sxml-match g
         [(TVGuide (@ (start ,start-date)
                      (end ,end-date))
                   (Channel (Name ,nm) ,[prog -> p] ...) ...)
          `(html (head (title "TV Guide"))
                 (body (h1 "TV Guide")
                       (div (h2 ,nm) ,p ...) ...))]))

‘sxml-match-let’ and ‘sxml-match-let*’
--------------------------------------

 -- Scheme Syntax: sxml-match-let ((pat expr) ...) expression0
          expression ...
 -- Scheme Syntax: sxml-match-let* ((pat expr) ...) expression0
          expression ...
     These forms generalize the ‘let’ and ‘let*’ forms of Scheme to
     allow an XML pattern in the binding position, rather than a simple
     variable.

   For example, the expression below:

     (sxml-match-let ([(a ,i ,j) '(a 1 2)])
       (+ i j))

   binds the variables I and J to ‘1’ and ‘2’ in the XML value given.

   ---------- Footnotes ----------

   (1) This example is taken from a paper by Krishnamurthi et al.  Their
paper was the first to show the usefulness of the ‘syntax-rules’ style
of pattern matching for transformation of XML, though the language
described, XT3D, is an XML language.


File: guile.info,  Node: The Scheme shell (scsh),  Next: Curried Definitions,  Prev: sxml-match,  Up: Guile Modules

7.17 The Scheme shell (scsh)
============================

An incomplete port of the Scheme shell (scsh) was once available for
Guile as a separate package.  However this code has bitrotten somewhat.
The pieces are available in Guile’s legacy CVS repository, which may be
browsed at
<http://cvs.savannah.gnu.org/viewvc/guile/guile-scsh/?root=guile>.

   For information about scsh see <http://www.scsh.net/>.

   This bitrotting is a bit of a shame, as there is a good deal of
well-written Scheme code in scsh.  Adopting this code and porting it to
current Guile should be an educational experience, in addition to
providing something of value to Guile folks.


File: guile.info,  Node: Curried Definitions,  Next: Statprof,  Prev: The Scheme shell (scsh),  Up: Guile Modules

7.18 Curried Definitions
========================

The macros in this section are provided by
     (use-modules (ice-9 curried-definitions))
and replace those provided by default.

   Prior to Guile 2.0, Guile provided a type of definition known
colloquially as a “curried definition”.  The idea is to extend the
syntax of ‘define’ so that you can conveniently define procedures that
return procedures, up to any desired depth.

   For example,
     (define ((foo x) y)
       (list x y))
   is a convenience form of
     (define foo
       (lambda (x)
         (lambda (y)
           (list x y))))

 -- Scheme Syntax: define (… (name args …) …) body …
 -- Scheme Syntax: define* (… (name args …) …) body …
 -- Scheme Syntax: define-public (… (name args …) …) body …

     Create a top level variable NAME bound to the procedure with
     parameter list ARGS.  If NAME is itself a formal parameter list,
     then a higher order procedure is created using that
     formal-parameter list, and returning a procedure that has parameter
     list ARGS.  This nesting may occur to arbitrary depth.

     ‘define*’ is similar but the formal parameter lists take additional
     options as described in *note lambda* and define*::.  For example,
          (define* ((foo #:keys (bar 'baz) (quux 'zot)) frotz #:rest rest)
            (list bar quux frotz rest))

          ((foo #:quux 'foo) 1 2 3 4 5)
          ⇒ (baz foo 1 (2 3 4 5))

     ‘define-public’ is similar to ‘define’ but it also adds NAME to the
     list of exported bindings of the current module.


File: guile.info,  Node: Statprof,  Next: SXML,  Prev: Curried Definitions,  Up: Guile Modules

7.19 Statprof
=============

‘(statprof)’ is a fairly simple statistical profiler for Guile.

   A simple use of statprof would look like this:

     (statprof-reset 0 50000 #t)
     (statprof-start)
     (do-something)
     (statprof-stop)
     (statprof-display)

   This would reset statprof, clearing all accumulated statistics, then
start profiling, run some code, stop profiling, and finally display a
gprof flat-style table of statistics which will look something like
this:

       %   cumulative      self              self    total
      time    seconds   seconds    calls  ms/call  ms/call  name
      35.29      0.23      0.23     2002     0.11     0.11  -
      23.53      0.15      0.15     2001     0.08     0.08  positive?
      23.53      0.15      0.15     2000     0.08     0.08  +
      11.76      0.23      0.08     2000     0.04     0.11  do-nothing
       5.88      0.64      0.04     2001     0.02     0.32  loop
       0.00      0.15      0.00        1     0.00   150.59  do-something
      ...

   All of the numerical data with the exception of the calls column is
statistically approximate.  In the following column descriptions, and in
all of statprof, "time" refers to execution time (both user and system),
not wall clock time.

% time
     The percent of the time spent inside the procedure itself (not
     counting children).

cumulative seconds
     The total number of seconds spent in the procedure, including
     children.

self seconds
     The total number of seconds spent in the procedure itself (not
     counting children).

calls
     The total number of times the procedure was called.

self ms/call
     The average time taken by the procedure itself on each call, in ms.

total ms/call
     The average time taken by each call to the procedure, including
     time spent in child functions.

name
     The name of the procedure.

   The profiler uses ‘eq?’ and the procedure object itself to identify
the procedures, so it won’t confuse different procedures with the same
name.  They will show up as two different rows in the output.

   Right now the profiler is quite simplistic.  I cannot provide
call-graphs or other higher level information.  What you see in the
table is pretty much all there is.  Patches are welcome :-)

7.20 Implementation notes
=========================

The profiler works by setting the unix profiling signal ‘ITIMER_PROF’ to
go off after the interval you define in the call to ‘statprof-reset’.
When the signal fires, a sampling routine is run which looks at the
current procedure that’s executing, and then crawls up the stack, and
for each procedure encountered, increments that procedure’s sample
count.  Note that if a procedure is encountered multiple times on a
given stack, it is only counted once.  After the sampling is complete,
the profiler resets profiling timer to fire again after the appropriate
interval.

   Meanwhile, the profiler keeps track, via ‘get-internal-run-time’, how
much CPU time (system and user – which is also what ‘ITIMER_PROF’
tracks), has elapsed while code has been executing within a
statprof-start/stop block.

   The profiler also tries to avoid counting or timing its own code as
much as possible.

7.21 Usage
==========

 -- Function: statprof-active?
     Returns ‘#t’ if ‘statprof-start’ has been called more times than
     ‘statprof-stop’, ‘#f’ otherwise.

 -- Function: statprof-start
     Start the profiler.‘’

 -- Function: statprof-stop
     Stop the profiler.‘’

 -- Function: statprof-reset sample-seconds sample-microseconds
          count-calls? [full-stacks?]
     Reset the statprof sampler interval to SAMPLE-SECONDS and
     SAMPLE-MICROSECONDS.  If COUNT-CALLS? is true, arrange to
     instrument procedure calls as well as collecting statistical
     profiling data.  If FULL-STACKS? is true, collect all sampled
     stacks into a list for later analysis.

     Enables traps and debugging as necessary.

 -- Function: statprof-accumulated-time
     Returns the time accumulated during the last statprof run.‘’

 -- Function: statprof-sample-count
     Returns the number of samples taken during the last statprof run.‘’

 -- Function: statprof-fold-call-data proc init
     Fold PROC over the call-data accumulated by statprof.  Cannot be
     called while statprof is active.  PROC should take two arguments,
     ‘(CALL-DATA PRIOR-RESULT)’.

     Note that a given proc-name may appear multiple times, but if it
     does, it represents different functions with the same name.

 -- Function: statprof-proc-call-data proc
     Returns the call-data associated with PROC, or ‘#f’ if none is
     available.

 -- Function: statprof-call-data-name cd

 -- Function: statprof-call-data-calls cd

 -- Function: statprof-call-data-cum-samples cd

 -- Function: statprof-call-data-self-samples cd

 -- Function: statprof-call-data->stats call-data
     Returns an object of type ‘statprof-stats’.

 -- Function: statprof-stats-proc-name stats

 -- Function: statprof-stats-%-time-in-proc stats

 -- Function: statprof-stats-cum-secs-in-proc stats

 -- Function: statprof-stats-self-secs-in-proc stats

 -- Function: statprof-stats-calls stats

 -- Function: statprof-stats-self-secs-per-call stats

 -- Function: statprof-stats-cum-secs-per-call stats

 -- Function: statprof-display . _
     Displays a gprof-like summary of the statistics collected.  Unless
     an optional PORT argument is passed, uses the current output port.

 -- Function: statprof-display-anomolies
     A sanity check that attempts to detect anomolies in statprof’s
     statistics.‘’

 -- Function: statprof-fetch-stacks
     Returns a list of stacks, as they were captured since the last call
     to ‘statprof-reset’.

     Note that stacks are only collected if the FULL-STACKS? argument to
     ‘statprof-reset’ is true.

 -- Function: statprof-fetch-call-tree
     Return a call tree for the previous statprof run.

     The return value is a list of nodes, each of which is of the type:
     @@code
      node ::= (@@var@{proc@} @@var@{count@} . @@var@{nodes@})
     @@end code

 -- Function: statprof thunk [#:loop] [#:hz] [#:count-calls?]
          [#:full-stacks?]
     Profiles the execution of THUNK.

     The stack will be sampled HZ times per second, and the thunk itself
     will be called LOOP times.

     If COUNT-CALLS? is true, all procedure calls will be recorded.
     This operation is somewhat expensive.

     If FULL-STACKS? is true, at each sample, statprof will store away
     the whole call tree, for later analysis.  Use
     ‘statprof-fetch-stacks’ or ‘statprof-fetch-call-tree’ to retrieve
     the last-stored stacks.

 -- Special Form: with-statprof args
     Profiles the expressions in its body.

     Keyword arguments:

     ‘#:loop’
          Execute the body LOOP number of times, or ‘#f’ for no looping

          default: ‘#f’

     ‘#:hz’
          Sampling rate

          default: ‘20’

     ‘#:count-calls?’
          Whether to instrument each function call (expensive)

          default: ‘#f’

     ‘#:full-stacks?’
          Whether to collect away all sampled stacks into a list

          default: ‘#f’

 -- Function: gcprof thunk [#:loop] [#:full-stacks?]
     Do an allocation profile of the execution of THUNK.

     The stack will be sampled soon after every garbage collection,
     yielding an approximate idea of what is causing allocation in your
     program.

     Since GC does not occur very frequently, you may need to use the
     LOOP parameter, to cause THUNK to be called LOOP times.

     If FULL-STACKS? is true, at each sample, statprof will store away
     the whole call tree, for later analysis.  Use
     ‘statprof-fetch-stacks’ or ‘statprof-fetch-call-tree’ to retrieve
     the last-stored stacks.


File: guile.info,  Node: SXML,  Next: Texinfo Processing,  Prev: Statprof,  Up: Guile Modules

7.22 SXML
=========

SXML is a native representation of XML in terms of standard Scheme data
types: lists, symbols, and strings.  For example, the simple XML
fragment:

     <parrot type="African Grey"><name>Alfie</name></parrot>

   may be represented with the following SXML:

     (parrot (@ (type "African Grey)) (name "Alfie"))

   SXML is very general, and is capable of representing all of XML.
Formally, this means that SXML is a conforming implementation of the
http://www.w3.org/TR/xml-infoset/ (XML Information Set) standard.

   Guile includes several facilities for working with XML and SXML:
parsers, serializers, and transformers.

* Menu:

* SXML Overview::              XML, as it was meant to be
* Reading and Writing XML::    Convenient XML parsing and serializing
* SSAX::                       Custom functional-style XML parsers
* Transforming SXML::          Munging SXML with ‘pre-post-order’
* SXML Tree Fold::             Fold-based SXML transformations
* SXPath::                     XPath for SXML
* sxml apply-templates::       A more XSLT-like approach to SXML transformations
* sxml ssax input-parse::      The SSAX tokenizer, optimized for Guile


File: guile.info,  Node: SXML Overview,  Next: Reading and Writing XML,  Up: SXML

7.22.1 SXML Overview
--------------------

(This section needs to be written; volunteers welcome.)


File: guile.info,  Node: Reading and Writing XML,  Next: SSAX,  Prev: SXML Overview,  Up: SXML

7.22.2 Reading and Writing XML
------------------------------

The ‘(sxml simple)’ module presents a basic interface for parsing XML
from a port into the Scheme SXML format, and for serializing it back to
text.

     (use-modules (sxml simple))

 -- Scheme Procedure: xml->sxml [string-or-port] [#:namespaces='()]
          [#:declare-namespaces?=#t] [#:trim-whitespace?=#f]
          [#:entities='()] [#:default-entity-handler=#f]
          [#:doctype-handler=#f]
     Use SSAX to parse an XML document into SXML. Takes one optional
     argument, STRING-OR-PORT, which defaults to the current input port.
     Returns the resulting SXML document.  If STRING-OR-PORT is a port,
     it will be left pointing at the next available character in the
     port.

   As is normal in SXML, XML elements parse as tagged lists.
Attributes, if any, are placed after the tag, within an ‘@’ element.
The root of the resulting XML will be contained in a special tag,
‘*TOP*’.  This tag will contain the root element of the XML, but also
any prior processing instructions.

     (xml->sxml "<foo/>")
     ⇒ (*TOP* (foo))
     (xml->sxml "<foo>text</foo>")
     ⇒ (*TOP* (foo "text"))
     (xml->sxml "<foo kind=\"bar\">text</foo>")
     ⇒ (*TOP* (foo (@ (kind "bar")) "text"))
     (xml->sxml "<?xml version=\"1.0\"?><foo/>")
     ⇒ (*TOP* (*PI* xml "version=\"1.0\"") (foo))

   All namespaces in the XML document must be declared, via ‘xmlns’
attributes.  SXML elements built from non-default namespaces will have
their tags prefixed with their URI. Users can specify custom prefixes
for certain namespaces with the ‘#:namespaces’ keyword argument to
‘xml->sxml’.

     (xml->sxml "<foo xmlns=\"http://example.org/ns1\">text</foo>")
     ⇒ (*TOP* (http://example.org/ns1:foo "text"))
     (xml->sxml "<foo xmlns=\"http://example.org/ns1\">text</foo>"
                #:namespaces '((ns1 . "http://example.org/ns1")))
     ⇒ (*TOP* (ns1:foo "text"))
     (xml->sxml "<foo xmlns:bar=\"http://example.org/ns2\"><bar:baz/></foo>"
                #:namespaces '((ns2 . "http://example.org/ns2")))
     ⇒ (*TOP* (foo (ns2:baz)))

   By default, namespaces passed to ‘xml->sxml’ are treated as if they
were declared on the root element.  Passing a false
‘#:declare-namespaces?’ argument will disable this behavior, requiring
in-document declarations of namespaces before use..

     (xml->sxml "<foo><ns2:baz/></foo>"
                #:namespaces '((ns2 . "http://example.org/ns2")))
     ⇒ (*TOP* (foo (ns2:baz)))
     (xml->sxml "<foo><ns2:baz/></foo>"
                #:namespaces '((ns2 . "http://example.org/ns2"))
                #:declare-namespaces? #f)
     ⇒ error: undeclared namespace: `bar'

   By default, all whitespace in XML is significant.  Passing the
‘#:trim-whitespace?’ keyword argument to ‘xml->sxml’ will trim
whitespace in front, behind and between elements, treating it as
“unsignificant”.  Whitespace in text fragments is left alone.

     (xml->sxml "<foo>\n<bar> Alfie the parrot! </bar>\n</foo>")
     ⇒ (*TOP* (foo "\n" (bar " Alfie the parrot! ") "\n"))
     (xml->sxml "<foo>\n<bar> Alfie the parrot! </bar>\n</foo>"
                #:trim-whitespace? #t)
     ⇒ (*TOP* (foo (bar " Alfie the parrot! ")))

   Parsed entities may be declared with the ‘#:entities’ keyword
argument, or handled with the ‘#:default-entity-handler’.  By default,
only the standard ‘&lt;’, ‘&gt;’, ‘&amp;’, ‘&apos;’ and ‘&quot;’
entities are defined, as well as the ‘&#N;’ and ‘&#xN;’ (decimal and
hexadecimal) numeric character entities.

     (xml->sxml "<foo>&amp;</foo>")
     ⇒ (*TOP* (foo "&"))
     (xml->sxml "<foo>&nbsp;</foo>")
     ⇒ error: undefined entity: nbsp
     (xml->sxml "<foo>&#xA0;</foo>")
     ⇒ (*TOP* (foo "\xa0"))
     (xml->sxml "<foo>&nbsp;</foo>"
                #:entities '((nbsp . "\xa0")))
     ⇒ (*TOP* (foo "\xa0"))
     (xml->sxml "<foo>&nbsp; &foo;</foo>"
                #:default-entity-handler
                (lambda (port name)
                  (case name
                    ((nbsp) "\xa0")
                    (else
                     (format (current-warning-port)
                             "~a:~a:~a: undefined entitity: ~a\n"
                             (or (port-filename port) "<unknown file>")
                             (port-line port) (port-column port)
                             name)
                     (symbol->string name)))))
     ⊣ <unknown file>:0:17: undefined entitity: foo
     ⇒ (*TOP* (foo "\xa0 foo"))

   By default, ‘xml->sxml’ skips over the ‘<!DOCTYPE>’ declaration, if
any.  This behavior can be overridden with the ‘#:doctype-handler’
argument, which should be a procedure of three arguments: the "docname"
(a symbol), "systemid" (a string), and the internal doctype subset (as a
string or ‘#f’ if not present).

   The handler should return keyword arguments as multiple values, as if
it were calling its continuation with keyword arguments.  The
continuation accepts the ‘#:entities’ and ‘#:namespaces’ keyword
arguments, in the same format that ‘xml->sxml’ itself takes.  These
entities and namespaces will be prepended to those given to the
‘xml->sxml’ invocation.

     (define (handle-foo docname systemid internal-subset)
       (case docname
         ((foo)
          (values #:entities '((greets . "<i>Hello, world!</i>"))))
         (else
          (values))))

     (xml->sxml "<!DOCTYPE foo><p>&greets;</p>"
                #:doctype-handler handle-foo)
     ⇒ (*TOP* (p (i "Hello, world!")))

   If the document has no doctype declaration, the DOCTYPE-HANDLER is
invoked with ‘#f’ for the three arguments.

   In the future, the continuation may accept other keyword arguments,
for example to validate the parsed SXML against the doctype.

 -- Scheme Procedure: sxml->xml tree [port]
     Serialize the SXML tree TREE as XML. The output will be written to
     the current output port, unless the optional argument PORT is
     present.

 -- Scheme Procedure: sxml->string sxml
     Detag an sxml tree SXML into a string.  Does not perform any
     formatting.


File: guile.info,  Node: SSAX,  Next: Transforming SXML,  Prev: Reading and Writing XML,  Up: SXML

7.22.3 SSAX: A Functional XML Parsing Toolkit
---------------------------------------------

Guile’s XML parser is based on Oleg Kiselyov’s powerful XML parsing
toolkit, SSAX.

7.22.3.1 History
................

Back in the 1990s, when the world was young again and XML was the
solution to all of its problems, there were basically two kinds of XML
parsers out there: DOM parsers and SAX parsers.

   A DOM parser reads through an entire XML document, building up a tree
of “DOM objects” representing the document structure.  They are very
easy to use, but sometimes you don’t actually want all of the
information in a document; building an object tree is not necessary if
all you want to do is to count word frequencies in a document, for
example.

   SAX parsers were created to give the programmer more control on the
parsing process.  A programmer gives the SAX parser a number of
“callbacks”: functions that will be called on various features of the
XML stream as they are encountered.  SAX parsers are more efficient, but
much harder to user, as users typically have to manually maintain a
stack of open elements.

   Kiselyov realized that the SAX programming model could be made much
simpler if the callbacks were formulated not as a linear fold across the
features of the XML stream, but as a _tree fold_ over the structure
implicit in the XML. In this way, the user has a very convenient,
functional-style interface that can still generate optimal parsers.

   The ‘xml->sxml’ interface from the ‘(sxml simple)’ module is a
DOM-style parser built using SSAX, though it returns SXML instead of DOM
objects.

7.22.3.2 Implementation
.......................

‘(sxml ssax)’ is a package of low-to-high level lexing and parsing
procedures that can be combined to yield a SAX, a DOM, a validating
parser, or a parser intended for a particular document type.  The
procedures in the package can be used separately to tokenize or parse
various pieces of XML documents.  The package supports XML Namespaces,
internal and external parsed entities, user-controlled handling of
whitespace, and validation.  This module therefore is intended to be a
framework, a set of “Lego blocks” you can use to build a parser
following any discipline and performing validation to any degree.  As an
example of the parser construction, this file includes a semi-validating
SXML parser.

   SSAX has a “sequential” feel of SAX yet a “functional style” of DOM.
Like a SAX parser, the framework scans the document only once and
permits incremental processing.  An application that handles document
elements in order can run as efficiently as possible.  _Unlike_ a SAX
parser, the framework does not require an application register stateful
callbacks and surrender control to the parser.  Rather, it is the
application that can drive the framework – calling its functions to get
the current lexical or syntax element.  These functions do not maintain
or mutate any state save the input port.  Therefore, the framework
permits parsing of XML in a pure functional style, with the input port
being a monad (or a linear, read-once parameter).

   Besides the PORT, there is another monad – SEED.  Most of the middle-
and high-level parsers are single-threaded through the SEED.  The
functions of this framework do not process or affect the SEED in any
way: they simply pass it around as an instance of an opaque datatype.
User functions, on the other hand, can use the seed to maintain user’s
state, to accumulate parsing results, etc.  A user can freely mix his
own functions with those of the framework.  On the other hand, the user
may wish to instantiate a high-level parser: ‘SSAX:make-elem-parser’ or
‘SSAX:make-parser’.  In the latter case, the user must provide functions
of specific signatures, which are called at predictable moments during
the parsing: to handle character data, element data, or processing
instructions (PI). The functions are always given the SEED, among other
parameters, and must return the new SEED.

   From a functional point of view, XML parsing is a combined
pre-post-order traversal of a “tree” that is the XML document itself.
This down-and-up traversal tells the user about an element when its
start tag is encountered.  The user is notified about the element once
more, after all element’s children have been handled.  The process of
XML parsing therefore is a fold over the raw XML document.  Unlike a
fold over trees defined in [1], the parser is necessarily
single-threaded – obviously as elements in a text XML document are laid
down sequentially.  The parser therefore is a tree fold that has been
transformed to accept an accumulating parameter [1,2].

   Formally, the denotational semantics of the parser can be expressed
as

      parser:: (Start-tag -> Seed -> Seed) ->
     	   (Start-tag -> Seed -> Seed -> Seed) ->
     	   (Char-Data -> Seed -> Seed) ->
     	   XML-text-fragment -> Seed -> Seed
      parser fdown fup fchar "<elem attrs> content </elem>" seed
       = fup "<elem attrs>" seed
     	(parser fdown fup fchar "content" (fdown "<elem attrs>" seed))

      parser fdown fup fchar "char-data content" seed
       = parser fdown fup fchar "content" (fchar "char-data" seed)

      parser fdown fup fchar "elem-content content" seed
       = parser fdown fup fchar "content" (
     	parser fdown fup fchar "elem-content" seed)

   Compare the last two equations with the left fold

      fold-left kons elem:list seed = fold-left kons list (kons elem seed)

   The real parser created by ‘SSAX:make-parser’ is slightly more
complicated, to account for processing instructions, entity references,
namespaces, processing of document type declaration, etc.

   The XML standard document referred to in this module is
<http://www.w3.org/TR/1998/REC-xml-19980210.html>

   The present file also defines a procedure that parses the text of an
XML document or of a separate element into SXML, an S-expression-based
model of an XML Information Set.  SXML is also an Abstract Syntax Tree
of an XML document.  SXML is similar but not identical to DOM; SXML is
particularly suitable for Scheme-based XML/HTML authoring, SXPath
queries, and tree transformations.  See SXML.html for more details.
SXML is a term implementation of evaluation of the XML document [3].
The other implementation is context-passing.

   The present frameworks fully supports the XML Namespaces
Recommendation: <http://www.w3.org/TR/REC-xml-names/>.

   Other links:

[1]
     Jeremy Gibbons, Geraint Jones, "The Under-appreciated Unfold,"
     Proc.  ICFP’98, 1998, pp.  273-279.

[2]
     Richard S. Bird, The promotion and accumulation strategies in
     transformational programming, ACM Trans.  Progr.  Lang.  Systems,
     6(4):487-504, October 1984.

[3]
     Ralf Hinze, "Deriving Backtracking Monad Transformers," Functional
     Pearl.  Proc ICFP’00, pp.  186-197.

7.22.3.3 Usage
..............

 -- Scheme Procedure: current-ssax-error-port

 -- Scheme Procedure: with-ssax-error-to-port port thunk

 -- Scheme Procedure: xml-token? _
      -- Scheme Procedure: pair? x
          Return `#t' if X is a pair; otherwise return `#f'.



 -- Scheme Syntax: xml-token-kind token

 -- Scheme Syntax: xml-token-head token

 -- Scheme Procedure: make-empty-attlist

 -- Scheme Procedure: attlist-add attlist name-value

 -- Scheme Procedure: attlist-null? x
     Return ‘#t’ if X is the empty list, else ‘#f’.

 -- Scheme Procedure: attlist-remove-top attlist

 -- Scheme Procedure: attlist->alist attlist

 -- Scheme Procedure: attlist-fold kons knil lis1

 -- Scheme Procedure: define-parsed-entity! entity str
     Define a new parsed entity.  ENTITY should be a symbol.

     Instances of &ENTITY; in XML text will be replaced with the string
     STR, which will then be parsed.

 -- Scheme Procedure: reset-parsed-entity-definitions!
     Restore the set of parsed entity definitions to its initial state.

 -- Scheme Procedure: ssax:uri-string->symbol uri-str

 -- Scheme Procedure: ssax:skip-internal-dtd port

 -- Scheme Procedure: ssax:read-pi-body-as-string port

 -- Scheme Procedure: ssax:reverse-collect-str-drop-ws fragments

 -- Scheme Procedure: ssax:read-markup-token port

 -- Scheme Procedure: ssax:read-cdata-body port str-handler seed

 -- Scheme Procedure: ssax:read-char-ref port

 -- Scheme Procedure: ssax:read-attributes port entities

 -- Scheme Procedure: ssax:complete-start-tag tag-head port elems
          entities namespaces

 -- Scheme Procedure: ssax:read-external-id port

 -- Scheme Procedure: ssax:read-char-data port expect-eof? str-handler
          seed

 -- Scheme Procedure: ssax:xml->sxml port namespace-prefix-assig

 -- Scheme Syntax: ssax:make-parser . kw-val-pairs

 -- Scheme Syntax: ssax:make-pi-parser orig-handlers

 -- Scheme Syntax: ssax:make-elem-parser my-new-level-seed
          my-finish-element my-char-data-handler my-pi-handlers


File: guile.info,  Node: Transforming SXML,  Next: SXML Tree Fold,  Prev: SSAX,  Up: SXML

7.22.4 Transforming SXML
------------------------

7.22.4.1 Overview
.................

SXML expression tree transformers
=================================

Pre-Post-order traversal of a tree and creation of a new tree
-------------------------------------------------------------

     pre-post-order:: <tree> x <bindings> -> <new-tree>

   where

      <bindings> ::= (<binding> ...)
      <binding> ::= (<trigger-symbol> *preorder* . <handler>) |
                    (<trigger-symbol> *macro* . <handler>) |
     		(<trigger-symbol> <new-bindings> . <handler>) |
     		(<trigger-symbol> . <handler>)
      <trigger-symbol> ::= XMLname | *text* | *default*
      <handler> :: <trigger-symbol> x [<tree>] -> <new-tree>

   The pre-post-order function visits the nodes and nodelists
pre-post-order (depth-first).  For each ‘<Node>’ of the form ‘(NAME
<Node> ...)’, it looks up an association with the given NAME among its
<BINDINGS>.  If failed, ‘pre-post-order’ tries to locate a ‘*default*’
binding.  It’s an error if the latter attempt fails as well.  Having
found a binding, the ‘pre-post-order’ function first checks to see if
the binding is of the form

     	(<trigger-symbol> *preorder* . <handler>)

   If it is, the handler is ’applied’ to the current node.  Otherwise,
the pre-post-order function first calls itself recursively for each
child of the current node, with <NEW-BINDINGS> prepended to the
<BINDINGS> in effect.  The result of these calls is passed to the
<HANDLER> (along with the head of the current <NODE>).  To be more
precise, the handler is _applied_ to the head of the current node and
its processed children.  The result of the handler, which should also be
a ‘<tree>’, replaces the current <NODE>.  If the current <NODE> is a
text string or other atom, a special binding with a symbol ‘*text*’ is
looked up.

   A binding can also be of a form

     	(<trigger-symbol> *macro* . <handler>)

   This is equivalent to ‘*preorder*’ described above.  However, the
result is re-processed again, with the current stylesheet.

7.22.4.2 Usage
..............

 -- Scheme Procedure: SRV:send-reply . fragments
     Output the FRAGMENTS to the current output port.

     The fragments are a list of strings, characters, numbers, thunks,
     ‘#f’, ‘#t’ – and other fragments.  The function traverses the tree
     depth-first, writes out strings and characters, executes thunks,
     and ignores ‘#f’ and ‘'()’.  The function returns ‘#t’ if anything
     was written at all; otherwise the result is ‘#f’ If ‘#t’ occurs
     among the fragments, it is not written out but causes the result of
     ‘SRV:send-reply’ to be ‘#t’.

 -- Scheme Procedure: foldts fdown fup fhere seed tree

 -- Scheme Procedure: post-order tree bindings

 -- Scheme Procedure: pre-post-order tree bindings

 -- Scheme Procedure: replace-range beg-pred end-pred forest


File: guile.info,  Node: SXML Tree Fold,  Next: SXPath,  Prev: Transforming SXML,  Up: SXML

7.22.5 SXML Tree Fold
---------------------

7.22.5.1 Overview
.................

‘(sxml fold)’ defines a number of variants of the "fold" algorithm for
use in transforming SXML trees.  Additionally it defines the layout
operator, ‘fold-layout’, which might be described as a context-passing
variant of SSAX’s ‘pre-post-order’.

7.22.5.2 Usage
..............

 -- Scheme Procedure: foldt fup fhere tree
     The standard multithreaded tree fold.

     FUP is of type [a] -> a.  FHERE is of type object -> a.

 -- Scheme Procedure: foldts fdown fup fhere seed tree
     The single-threaded tree fold originally defined in SSAX. *Note
     SSAX::, for more information.

 -- Scheme Procedure: foldts* fdown fup fhere seed tree
     A variant of ‘foldts’ that allows pre-order tree rewrites.
     Originally defined in Andy Wingo’s 2007 paper, _Applications of
     fold to XML transformation_.

 -- Scheme Procedure: fold-values proc list . seeds
     A variant of ‘fold’ that allows multi-valued seeds.  Note that the
     order of the arguments differs from that of ‘fold’.  *Note SRFI-1
     Fold and Map::.

 -- Scheme Procedure: foldts*-values fdown fup fhere tree . seeds
     A variant of ‘foldts*’ that allows multi-valued seeds.  Originally
     defined in Andy Wingo’s 2007 paper, _Applications of fold to XML
     transformation_.

 -- Scheme Procedure: fold-layout tree bindings params layout stylesheet
     A traversal combinator in the spirit of ‘pre-post-order’.  *Note
     Transforming SXML::.

     ‘fold-layout’ was originally presented in Andy Wingo’s 2007 paper,
     _Applications of fold to XML transformation_.

          bindings := (<binding>...)
          binding  := (<tag> <bandler-pair>...)
                    | (*default* . <post-handler>)
                    | (*text* . <text-handler>)
          tag      := <symbol>
          handler-pair := (pre-layout . <pre-layout-handler>)
                    | (post . <post-handler>)
                    | (bindings . <bindings>)
                    | (pre . <pre-handler>)
                    | (macro . <macro-handler>)

     PRE-LAYOUT-HANDLER
          A function of three arguments:

          KIDS
               the kids of the current node, before traversal

          PARAMS
               the params of the current node

          LAYOUT
               the layout coming into this node

          PRE-LAYOUT-HANDLER is expected to use this information to
          return a layout to pass to the kids.  The default
          implementation returns the layout given in the arguments.

     POST-HANDLER
          A function of five arguments:

          TAG
               the current tag being processed

          PARAMS
               the params of the current node

          LAYOUT
               the layout coming into the current node, before any kids
               were processed

          KLAYOUT
               the layout after processing all of the children

          KIDS
               the already-processed child nodes

          POST-HANDLER should return two values, the layout to pass to
          the next node and the final tree.

     TEXT-HANDLER
          TEXT-HANDLER is a function of three arguments:

          TEXT
               the string

          PARAMS
               the current params

          LAYOUT
               the current layout

          TEXT-HANDLER should return two values, the layout to pass to
          the next node and the value to which the string should
          transform.


File: guile.info,  Node: SXPath,  Next: sxml ssax input-parse,  Prev: SXML Tree Fold,  Up: SXML

7.22.6 SXPath
-------------

7.22.6.1 Overview
.................

SXPath: SXML Query Language
===========================

SXPath is a query language for SXML, an instance of XML Information set
(Infoset) in the form of s-expressions.  See ‘(sxml ssax)’ for the
definition of SXML and more details.  SXPath is also a translation into
Scheme of an XML Path Language, XPath (http://www.w3.org/TR/xpath).
XPath and SXPath describe means of selecting a set of Infoset’s items or
their properties.

   To facilitate queries, XPath maps the XML Infoset into an explicit
tree, and introduces important notions of a location path and a current,
context node.  A location path denotes a selection of a set of nodes
relative to a context node.  Any XPath tree has a distinguished, root
node – which serves as the context node for absolute location paths.
Location path is recursively defined as a location step joined with a
location path.  A location step is a simple query of the database
relative to a context node.  A step may include expressions that further
filter the selected set.  Each node in the resulting set is used as a
context node for the adjoining location path.  The result of the step is
a union of the sets returned by the latter location paths.

   The SXML representation of the XML Infoset (see SSAX.scm) is rather
suitable for querying as it is.  Bowing to the XPath specification, we
will refer to SXML information items as ’Nodes’:

      	<Node> ::= <Element> | <attributes-coll> | <attrib>
      		   | "text string" | <PI>

   This production can also be described as

     	<Node> ::= (name . <Nodeset>) | "text string"

   An (ordered) set of nodes is just a list of the constituent nodes:

      	<Nodeset> ::= (<Node> ...)

   Nodesets, and Nodes other than text strings are both lists.  A
<Nodeset> however is either an empty list, or a list whose head is not a
symbol.  A symbol at the head of a node is either an XML name (in which
case it’s a tag of an XML element), or an administrative name such as
’@’.  This uniform list representation makes processing rather simple
and elegant, while avoiding confusion.  The multi-branch tree structure
formed by the mutually-recursive datatypes <Node> and <Nodeset> lends
itself well to processing by functional languages.

   A location path is in fact a composite query over an XPath tree or
its branch.  A singe step is a combination of a projection, selection or
a transitive closure.  Multiple steps are combined via join and union
operations.  This insight allows us to _elegantly_ implement XPath as a
sequence of projection and filtering primitives – converters – joined by
"combinators".  Each converter takes a node and returns a nodeset which
is the result of the corresponding query relative to that node.  A
converter can also be called on a set of nodes.  In that case it returns
a union of the corresponding queries over each node in the set.  The
union is easily implemented as a list append operation as all nodes in a
SXML tree are considered distinct, by XPath conventions.  We also
preserve the order of the members in the union.  Query combinators are
high-order functions: they take converter(s) (which is a Node|Nodeset ->
Nodeset function) and compose or otherwise combine them.  We will be
concerned with only relative location paths [XPath]: an absolute
location path is a relative path applied to the root node.

   Similarly to XPath, SXPath defines full and abbreviated notations for
location paths.  In both cases, the abbreviated notation can be
mechanically expanded into the full form by simple rewriting rules.  In
case of SXPath the corresponding rules are given as comments to a sxpath
function, below.  The regression test suite at the end of this file
shows a representative sample of SXPaths in both notations, juxtaposed
with the corresponding XPath expressions.  Most of the samples are
borrowed literally from the XPath specification, while the others are
adjusted for our running example, tree1.

7.22.6.2 Usage
..............

 -- Scheme Procedure: nodeset? x

 -- Scheme Procedure: node-typeof? crit

 -- Scheme Procedure: node-eq? other

 -- Scheme Procedure: node-equal? other

 -- Scheme Procedure: node-pos n

 -- Scheme Procedure: filter pred?
      -- Scheme Procedure: filter pred list
          Return all the elements of 2nd arg LIST that satisfy predicate
          PRED.  The list is not disordered - elements that appear in the
          result list occur in the same order as they occur in the argument
          list.  The returned list may share a common tail with the argument
          list.  The dynamic order in which the various applications of pred
          are made is not specified.

               (filter even? '(0 7 8 8 43 -4)) => (0 8 8 -4)



 -- Scheme Procedure: take-until pred?

 -- Scheme Procedure: take-after pred?

 -- Scheme Procedure: map-union proc lst

 -- Scheme Procedure: node-reverse node-or-nodeset

 -- Scheme Procedure: node-trace title

 -- Scheme Procedure: select-kids test-pred?

 -- Scheme Procedure: node-self pred?
      -- Scheme Procedure: filter pred list
          Return all the elements of 2nd arg LIST that satisfy predicate
          PRED.  The list is not disordered - elements that appear in the
          result list occur in the same order as they occur in the argument
          list.  The returned list may share a common tail with the argument
          list.  The dynamic order in which the various applications of pred
          are made is not specified.

               (filter even? '(0 7 8 8 43 -4)) => (0 8 8 -4)



 -- Scheme Procedure: node-join . selectors

 -- Scheme Procedure: node-reduce . converters

 -- Scheme Procedure: node-or . converters

 -- Scheme Procedure: node-closure test-pred?

 -- Scheme Procedure: node-parent rootnode

 -- Scheme Procedure: sxpath path


File: guile.info,  Node: sxml ssax input-parse,  Next: sxml apply-templates,  Prev: SXPath,  Up: SXML

7.22.7 (sxml ssax input-parse)
------------------------------

7.22.7.1 Overview
.................

A simple lexer.

   The procedures in this module surprisingly often suffice to parse an
input stream.  They either skip, or build and return tokens, according
to inclusion or delimiting semantics.  The list of characters to expect,
include, or to break at may vary from one invocation of a function to
another.  This allows the functions to easily parse even
context-sensitive languages.

   EOF is generally frowned on, and thrown up upon if encountered.
Exceptions are mentioned specifically.  The list of expected characters
(characters to skip until, or break-characters) may include an EOF
"character", which is to be coded as the symbol, ‘*eof*’.

   The input stream to parse is specified as a "port", which is usually
the last (and optional) argument.  It defaults to the current input port
if omitted.

   If the parser encounters an error, it will throw an exception to the
key ‘parser-error’.  The arguments will be of the form ‘(PORT MESSAGE
SPECIALISING-MSG*)’.

   The first argument is a port, which typically points to the offending
character or its neighborhood.  You can then use ‘port-column’ and
‘port-line’ to query the current position.  MESSAGE is the description
of the error.  Other arguments supply more details about the problem.

7.22.7.2 Usage
..............

 -- Scheme Procedure: peek-next-char [port]

 -- Scheme Procedure: assert-curr-char expected-chars comment [port]

 -- Scheme Procedure: skip-until arg [port]

 -- Scheme Procedure: skip-while skip-chars [port]

 -- Scheme Procedure: next-token prefix-skipped-chars break-chars
          [comment] [port]

 -- Scheme Procedure: next-token-of incl-list/pred [port]

 -- Scheme Procedure: read-text-line [port]

 -- Scheme Procedure: read-string n [port]

 -- Scheme Procedure: find-string-from-port? _ _ . _
     Looks for STR in <INPUT-PORT>, optionally within the first
     MAX-NO-CHAR characters.


File: guile.info,  Node: sxml apply-templates,  Next: sxml ssax input-parse,  Prev: sxml ssax input-parse,  Up: SXML

7.22.8 (sxml apply-templates)
-----------------------------

7.22.8.1 Overview
.................

Pre-order traversal of a tree and creation of a new tree:

     	apply-templates:: tree x <templates> -> <new-tree>

   where

      <templates> ::= (<template> ...)
      <template>  ::= (<node-test> <node-test> ... <node-test> . <handler>)
      <node-test> ::= an argument to node-typeof? above
      <handler>   ::= <tree> -> <new-tree>

   This procedure does a _normal_, pre-order traversal of an SXML tree.
It walks the tree, checking at each node against the list of matching
templates.

   If the match is found (which must be unique, i.e., unambiguous), the
corresponding handler is invoked and given the current node as an
argument.  The result from the handler, which must be a ‘<tree>’, takes
place of the current node in the resulting tree.  The name of the
function is not accidental: it resembles rather closely an
‘apply-templates’ function of XSLT.

7.22.8.2 Usage
..............

 -- Scheme Procedure: apply-templates tree templates


File: guile.info,  Node: Texinfo Processing,  Prev: SXML,  Up: Guile Modules

7.23 Texinfo Processing
=======================

* Menu:

* texinfo::              Parse texinfo files or fragments into ‘stexi’, a scheme representation
* texinfo docbook::      Transform a subset of docbook into ‘stexi’
* texinfo html::         Transform ‘stexi’ into HTML
* texinfo indexing::     Extract an index from a piece of ‘stexi’
* texinfo string-utils::  String utility functions used by the texinfo processor
* texinfo plain-text::   Render ‘stexi’ as plain text
* texinfo serialize::    Render ‘stexi’ as texinfo
* texinfo reflection::   Enable texinfo across Guile’s help system


File: guile.info,  Node: texinfo,  Next: texinfo docbook,  Up: Texinfo Processing

7.23.1 (texinfo)
----------------

7.23.1.1 Overview
.................

Texinfo processing in scheme
----------------------------

This module parses texinfo into SXML. TeX will always be the processor
of choice for print output, of course.  However, although ‘makeinfo’
works well for info, its output in other formats is not very
customizable, and the program is not extensible as a whole.  This module
aims to provide an extensible framework for texinfo processing that
integrates texinfo into the constellation of SXML processing tools.

Notes on the SXML vocabulary
----------------------------

Consider the following texinfo fragment:

      @deffn Primitive set-car! pair value
      This function...
      @end deffn

   Logically, the category (Primitive), name (set-car!), and arguments
(pair value) are “attributes” of the deffn, with the description as the
content.  However, texinfo allows for @-commands within the arguments to
an environment, like ‘@deffn’, which means that texinfo “attributes” are
PCDATA. XML attributes, on the other hand, are CDATA. For this reason,
“attributes” of texinfo @-commands are called “arguments”, and are
grouped under the special element, ‘%’.

   Because ‘%’ is not a valid NCName, stexinfo is a superset of SXML. In
the interests of interoperability, this module provides a conversion
function to replace the ‘%’ with ‘texinfo-arguments’.

7.23.1.2 Usage
..............

 -- Function: call-with-file-and-dir filename proc
     Call the one-argument procedure PROC with an input port that reads
     from FILENAME.  During the dynamic extent of PROC’s execution, the
     current directory will be ‘(dirname FILENAME)’.  This is useful for
     parsing documents that can include files by relative path name.

 -- Variable: texi-command-specs

 -- Function: texi-command-depth command max-depth
     Given the texinfo command COMMAND, return its nesting level, or
     ‘#f’ if it nests too deep for MAX-DEPTH.

     Examples:

           (texi-command-depth 'chapter 4)        ⇒ 1
           (texi-command-depth 'top 4)            ⇒ 0
           (texi-command-depth 'subsection 4)     ⇒ 3
           (texi-command-depth 'appendixsubsec 4) ⇒ 3
           (texi-command-depth 'subsection 2)     ⇒ #f

 -- Function: texi-fragment->stexi string-or-port
     Parse the texinfo commands in STRING-OR-PORT, and return the
     resultant stexi tree.  The head of the tree will be the special
     command, ‘*fragment*’.

 -- Function: texi->stexi port
     Read a full texinfo document from PORT and return the parsed stexi
     tree.  The parsing will start at the ‘@settitle’ and end at ‘@bye’
     or EOF.

 -- Function: stexi->sxml tree
     Transform the stexi tree TREE into sxml.  This involves replacing
     the ‘%’ element that keeps the texinfo arguments with an element
     for each argument.

     FIXME: right now it just changes % to ‘texinfo-arguments’ – that
     doesn’t hang with the idea of making a dtd at some point


File: guile.info,  Node: texinfo docbook,  Next: texinfo html,  Prev: texinfo,  Up: Texinfo Processing

7.23.2 (texinfo docbook)
------------------------

7.23.2.1 Overview
.................

This module exports procedures for transforming a limited subset of the
SXML representation of docbook into stexi.  It is not complete by any
means.  The intention is to gather a number of routines and stylesheets
so that external modules can parse specific subsets of docbook, for
example that set generated by certain tools.

7.23.2.2 Usage
..............

 -- Variable: *sdocbook->stexi-rules*

 -- Variable: *sdocbook-block-commands*

 -- Function: sdocbook-flatten sdocbook
     "Flatten" a fragment of sdocbook so that block elements do not nest
     inside each other.

     Docbook is a nested format, where e.g.  a ‘refsect2’ normally
     appears inside a ‘refsect1’.  Logical divisions in the document are
     represented via the tree topology; a ‘refsect2’ element _contains_
     all of the elements in its section.

     On the contrary, texinfo is a flat format, in which sections are
     marked off by standalone section headers like ‘@subsection’, and
     block elements do not nest inside each other.

     This function takes a nested sdocbook fragment SDOCBOOK and
     flattens all of the sections, such that e.g.

           (refsect1 (refsect2 (para "Hello")))

     becomes

           ((refsect1) (refsect2) (para "Hello"))

     Oftentimes (always?)  sectioning elements have ‘<title>’ as their
     first element child; users interested in processing the ‘refsect*’
     elements into proper sectioning elements like ‘chapter’ might be
     interested in ‘replace-titles’ and ‘filter-empty-elements’.  *Note
     replace-titles: texinfo docbook replace-titles, and *note
     filter-empty-elements: texinfo docbook filter-empty-elements.

     Returns a nodeset; that is to say, an untagged list of stexi
     elements.  *Note SXPath::, for the definition of a nodeset.

 -- Function: filter-empty-elements sdocbook
     Filters out empty elements in an sdocbook nodeset.  Mostly useful
     after running ‘sdocbook-flatten’.

 -- Function: replace-titles sdocbook-fragment
     Iterate over the sdocbook nodeset SDOCBOOK-FRAGMENT, transforming
     contiguous ‘refsect’ and ‘title’ elements into the appropriate
     texinfo sectioning command.  Most useful after having run
     ‘sdocbook-flatten’.

     For example:

           (replace-titles '((refsect1) (title "Foo") (para "Bar.")))
              ⇒ '((chapter "Foo") (para "Bar."))


File: guile.info,  Node: texinfo html,  Next: texinfo indexing,  Prev: texinfo docbook,  Up: Texinfo Processing

7.23.3 (texinfo html)
---------------------

7.23.3.1 Overview
.................

This module implements transformation from ‘stexi’ to HTML. Note that
the output of ‘stexi->shtml’ is actually SXML with the HTML vocabulary.
This means that the output can be further processed, and that it must
eventually be serialized by ‘sxml->xml’.  *Note Reading and Writing
XML::.

   References (i.e., the ‘@ref’ family of commands) are resolved by a
"ref-resolver".  *Note add-ref-resolver!: texinfo html
add-ref-resolver!.

7.23.3.2 Usage
..............

 -- Function: add-ref-resolver! proc
     Add PROC to the head of the list of ref-resolvers.  PROC will be
     expected to take the name of a node and the name of a manual and
     return the URL of the referent, or ‘#f’ to pass control to the next
     ref-resolver in the list.

     The default ref-resolver will return the concatenation of the
     manual name, ‘#’, and the node name.

 -- Function: stexi->shtml tree
     Transform the stexi TREE into shtml, resolving references via
     ref-resolvers.  See the module commentary for more details.

 -- Function: urlify str


File: guile.info,  Node: texinfo indexing,  Next: texinfo string-utils,  Prev: texinfo html,  Up: Texinfo Processing

7.23.4 (texinfo indexing)
-------------------------

7.23.4.1 Overview
.................

Given a piece of stexi, return an index of a specified variety.

   Note that currently, ‘stexi-extract-index’ doesn’t differentiate
between different kinds of index entries.  That’s a bug ;)

7.23.4.2 Usage
..............

 -- Function: stexi-extract-index tree manual-name kind
     Given an stexi tree TREE, index all of the entries of type KIND.
     KIND can be one of the predefined texinfo indices (‘concept’,
     ‘variable’, ‘function’, ‘key’, ‘program’, ‘type’) or one of the
     special symbols ‘auto’ or ‘all’.  ‘auto’ will scan the stext for a
     ‘(printindex)’ statement, and ‘all’ will generate an index from all
     entries, regardless of type.

     The returned index is a list of pairs, the CAR of which is the
     entry (a string) and the CDR of which is a node name (a string).


File: guile.info,  Node: texinfo string-utils,  Next: texinfo plain-text,  Prev: texinfo indexing,  Up: Texinfo Processing

7.23.5 (texinfo string-utils)
-----------------------------

7.23.5.1 Overview
.................

Module ‘(texinfo string-utils)’ provides various string-related
functions useful to Guile’s texinfo support.

7.23.5.2 Usage
..............

 -- Function: escape-special-chars str special-chars escape-char
     Returns a copy of STR with all given special characters preceded by
     the given ESCAPE-CHAR.

     SPECIAL-CHARS can either be a single character, or a string
     consisting of all the special characters.

          ;; make a string regexp-safe...
           (escape-special-chars "***(Example String)***"
                                "[]()/*."
                                #\\)
          => "\\*\\*\\*\\(Example String\\)\\*\\*\\*"

          ;; also can escape a singe char...
           (escape-special-chars "richardt@vzavenue.net"
                                #\@
                                #\@)
          => "richardt@@vzavenue.net"

 -- Function: transform-string str match? replace [start] [end]
     Uses MATCH? against each character in STR, and performs a
     replacement on each character for which matches are found.

     MATCH? may either be a function, a character, a string, or ‘#t’.
     If MATCH? is a function, then it takes a single character as input,
     and should return ‘#t’ for matches.  MATCH? is a character, it is
     compared to each string character using ‘char=?’.  If MATCH? is a
     string, then any character in that string will be considered a
     match.  ‘#t’ will cause every character to be a match.

     If REPLACE is a function, it is called with the matched character
     as an argument, and the returned value is sent to the output string
     via ‘display’.  If REPLACE is anything else, it is sent through the
     output string via ‘display’.

     Note that te replacement for the matched characters does not need
     to be a single character.  That is what differentiates this
     function from ‘string-map’, and what makes it useful for
     applications such as converting ‘#\&’ to ‘"&amp;"’ in web page
     text.  Some other functions in this module are just wrappers around
     common uses of ‘transform-string’.  Transformations not possible
     with this function should probably be done with regular
     expressions.

     If START and END are given, they control which portion of the
     string undergoes transformation.  The entire input string is still
     output, though.  So, if START is ‘5’, then the first five
     characters of STR will still appear in the returned string.

          ; these two are equivalent...
           (transform-string str #\space #\-) ; change all spaces to -'s
           (transform-string str (lambda (c) (char=? #\space c)) #\-)

 -- Function: expand-tabs str [tab-size]
     Returns a copy of STR with all tabs expanded to spaces.  TAB-SIZE
     defaults to 8.

     Assuming tab size of 8, this is equivalent to:

           (transform-string str #\tab "        ")

 -- Function: center-string str [width] [chr] [rchr]
     Returns a copy of STR centered in a field of WIDTH characters.  Any
     needed padding is done by character CHR, which defaults to
     ‘#\space’.  If RCHR is provided, then the padding to the right will
     use it instead.  See the examples below.  left and RCHR on the
     right.  The default WIDTH is 80.  The default CHR and RCHR is
     ‘#\space’.  The string is never truncated.

           (center-string "Richard Todd" 24)
          => "      Richard Todd      "

           (center-string " Richard Todd " 24 #\=)
          => "===== Richard Todd ====="

           (center-string " Richard Todd " 24 #\< #\>)
          => "<<<<< Richard Todd >>>>>"

 -- Function: left-justify-string str [width] [chr]
     ‘left-justify-string str [width chr]’.  Returns a copy of STR
     padded with CHR such that it is left justified in a field of WIDTH
     characters.  The default WIDTH is 80.  Unlike ‘string-pad’ from
     srfi-13, the string is never truncated.

 -- Function: right-justify-string str [width] [chr]
     Returns a copy of STR padded with CHR such that it is right
     justified in a field of WIDTH characters.  The default WIDTH is 80.
     The default CHR is ‘#\space’.  Unlike ‘string-pad’ from srfi-13,
     the string is never truncated.

 -- Function: collapse-repeated-chars str [chr] [num]
     Returns a copy of STR with all repeated instances of CHR collapsed
     down to at most NUM instances.  The default value for CHR is
     ‘#\space’, and the default value for NUM is 1.

           (collapse-repeated-chars "H  e  l  l  o")
          => "H e l l o"
           (collapse-repeated-chars "H--e--l--l--o" #\-)
          => "H-e-l-l-o"
           (collapse-repeated-chars "H-e--l---l----o" #\- 2)
          => "H-e--l--l--o"

 -- Function: make-text-wrapper [#:line-width] [#:expand-tabs?]
          [#:tab-width] [#:collapse-whitespace?] [#:subsequent-indent]
          [#:initial-indent] [#:break-long-words?]
     Returns a procedure that will split a string into lines according
     to the given parameters.

     ‘#:line-width’
          This is the target length used when deciding where to wrap
          lines.  Default is 80.

     ‘#:expand-tabs?’
          Boolean describing whether tabs in the input should be
          expanded.  Default is #t.

     ‘#:tab-width’
          If tabs are expanded, this will be the number of spaces to
          which they expand.  Default is 8.

     ‘#:collapse-whitespace?’
          Boolean describing whether the whitespace inside the existing
          text should be removed or not.  Default is #t.

          If text is already well-formatted, and is just being wrapped
          to fit in a different width, then set this to ‘#f’.  This way,
          many common text conventions (such as two spaces between
          sentences) can be preserved if in the original text.  If the
          input text spacing cannot be trusted, then leave this setting
          at the default, and all repeated whitespace will be collapsed
          down to a single space.

     ‘#:initial-indent’
          Defines a string that will be put in front of the first line
          of wrapped text.  Default is the empty string, “”.

     ‘#:subsequent-indent’
          Defines a string that will be put in front of all lines of
          wrapped text, except the first one.  Default is the empty
          string, “”.

     ‘#:break-long-words?’
          If a single word is too big to fit on a line, this setting
          tells the wrapper what to do.  Defaults to #t, which will
          break up long words.  When set to #f, the line will be
          allowed, even though it is longer than the defined
          ‘#:line-width’.

     The return value is a procedure of one argument, the input string,
     which returns a list of strings, where each element of the list is
     one line.

 -- Function: fill-string str . kwargs
     Wraps the text given in string STR according to the parameters
     provided in KWARGS, or the default setting if they are not given.
     Returns a single string with the wrapped text.  Valid keyword
     arguments are discussed in ‘make-text-wrapper’.

 -- Function: string->wrapped-lines str . kwargs
     ‘string->wrapped-lines str keywds ...’.  Wraps the text given in
     string STR according to the parameters provided in KEYWDS, or the
     default setting if they are not given.  Returns a list of strings
     representing the formatted lines.  Valid keyword arguments are
     discussed in ‘make-text-wrapper’.


File: guile.info,  Node: texinfo plain-text,  Next: texinfo serialize,  Prev: texinfo string-utils,  Up: Texinfo Processing

7.23.6 (texinfo plain-text)
---------------------------

7.23.6.1 Overview
.................

Transformation from stexi to plain-text.  Strives to re-create the
output from ‘info’; comes pretty damn close.

7.23.6.2 Usage
..............

 -- Function: stexi->plain-text tree
     Transform TREE into plain text.  Returns a string.


File: guile.info,  Node: texinfo serialize,  Next: texinfo reflection,  Prev: texinfo plain-text,  Up: Texinfo Processing

7.23.7 (texinfo serialize)
--------------------------

7.23.7.1 Overview
.................

Serialization of ‘stexi’ to plain texinfo.

7.23.7.2 Usage
..............

 -- Function: stexi->texi tree
     Serialize the stexi TREE into plain texinfo.


File: guile.info,  Node: texinfo reflection,  Prev: texinfo serialize,  Up: Texinfo Processing

7.23.8 (texinfo reflection)
---------------------------

7.23.8.1 Overview
.................

Routines to generare ‘stexi’ documentation for objects and modules.

   Note that in this context, an "object" is just a value associated
with a location.  It has nothing to do with GOOPS.

7.23.8.2 Usage
..............

 -- Function: module-stexi-documentation sym-name [%docs-resolver]
          [#:docs-resolver]
     Return documentation for the module named SYM-NAME.  The
     documentation will be formatted as ‘stexi’ (*note texinfo:
     texinfo.).

 -- Function: script-stexi-documentation scriptpath
     Return documentation for given script.  The documentation will be
     taken from the script’s commentary, and will be returned in the
     ‘stexi’ format (*note texinfo: texinfo.).

 -- Function: object-stexi-documentation _ [_] [#:force]

 -- Function: package-stexi-standard-copying name version updated years
          copyright-holder permissions
     Create a standard texinfo ‘copying’ section.

     YEARS is a list of years (as integers) in which the modules being
     documented were released.  All other arguments are strings.

 -- Function: package-stexi-standard-titlepage name version updated
          authors
     Create a standard GNU title page.

     AUTHORS is a list of ‘(NAME . EMAIL)’ pairs.  All other arguments
     are strings.

     Here is an example of the usage of this procedure:

           (package-stexi-standard-titlepage
            "Foolib"
            "3.2"
            "26 September 2006"
            '(("Alyssa P Hacker" . "alyssa@example.com"))
            '(2004 2005 2006)
            "Free Software Foundation, Inc."
            "Standard GPL permissions blurb goes here")

 -- Function: package-stexi-generic-menu name entries
     Create a menu from a generic alist of entries, the car of which
     should be the node name, and the cdr the description.  As an
     exception, an entry of ‘#f’ will produce a separator.

 -- Function: package-stexi-standard-menu name modules
          module-descriptions extra-entries
     Create a standard top node and menu, suitable for processing by
     makeinfo.

 -- Function: package-stexi-extended-menu name module-pairs script-pairs
          extra-entries
     Create an "extended" menu, like the standard menu but with a
     section for scripts.

 -- Function: package-stexi-standard-prologue name filename category
          description copying titlepage menu
     Create a standard prologue, suitable for later serialization to
     texinfo and .info creation with makeinfo.

     Returns a list of stexinfo forms suitable for passing to
     ‘package-stexi-documentation’ as the prologue.  *Note texinfo
     reflection package-stexi-documentation::, *note
     package-stexi-standard-titlepage: texinfo reflection
     package-stexi-standard-titlepage, *note
     package-stexi-standard-copying: texinfo reflection
     package-stexi-standard-copying, and *note
     package-stexi-standard-menu: texinfo reflection
     package-stexi-standard-menu.

 -- Function: package-stexi-documentation modules name filename prologue
          epilogue [#:module-stexi-documentation-args] [#:scripts]
     Create stexi documentation for a "package", where a package is a
     set of modules that is released together.

     MODULES is expected to be a list of module names, where a module
     name is a list of symbols.  The stexi that is returned will be
     titled NAME and a texinfo filename of FILENAME.

     PROLOGUE and EPILOGUE are lists of stexi forms that will be spliced
     into the output document before and after the generated modules
     documentation, respectively.  *Note texinfo reflection
     package-stexi-standard-prologue::, to create a conventional GNU
     texinfo prologue.

     MODULE-STEXI-DOCUMENTATION-ARGS is an optional argument that, if
     given, will be added to the argument list when
     ‘module-texi-documentation’ is called.  For example, it might be
     useful to define a ‘#:docs-resolver’ argument.

 -- Function: package-stexi-documentation-for-include modules
          module-descriptions [#:module-stexi-documentation-args]
     Create stexi documentation for a "package", where a package is a
     set of modules that is released together.

     MODULES is expected to be a list of module names, where a module
     name is a list of symbols.  Returns an stexinfo fragment.

     Unlike ‘package-stexi-documentation’, this function simply produces
     a menu and the module documentations instead of producing a full
     texinfo document.  This can be useful if you write part of your
     manual by hand, and just use ‘@include’ to pull in the
     automatically generated parts.

     MODULE-STEXI-DOCUMENTATION-ARGS is an optional argument that, if
     given, will be added to the argument list when
     ‘module-texi-documentation’ is called.  For example, it might be
     useful to define a ‘#:docs-resolver’ argument.


File: guile.info,  Node: GOOPS,  Next: Guile Implementation,  Prev: Guile Modules,  Up: Top

8 GOOPS
*******

GOOPS is the object oriented extension to Guile.  Its implementation is
derived from STk-3.99.3 by Erick Gallesio and version 1.3 of Gregor
Kiczales’ ‘Tiny-Clos’.  It is very close in spirit to CLOS, the Common
Lisp Object System, but is adapted for the Scheme language.

   GOOPS is a full object oriented system, with classes, objects,
multiple inheritance, and generic functions with multi-method dispatch.
Furthermore its implementation relies on a meta object protocol — which
means that GOOPS’s core operations are themselves defined as methods on
relevant classes, and can be customised by overriding or redefining
those methods.

   To start using GOOPS you first need to import the ‘(oop goops)’
module.  You can do this at the Guile REPL by evaluating:

     (use-modules (oop goops))

* Menu:

* Copyright Notice::
* Class Definition::
* Instance Creation::  
* Slot Options::
* Slot Description Example::
* Methods and Generic Functions::           
* Inheritance::                 
* Introspection::
* GOOPS Error Handling::
* GOOPS Object Miscellany::
* The Metaobject Protocol::
* Redefining a Class::
* Changing the Class of an Instance::


File: guile.info,  Node: Copyright Notice,  Next: Class Definition,  Up: GOOPS

8.1 Copyright Notice
====================

The material in this chapter is partly derived from the STk Reference
Manual written by Erick Gallesio, whose copyright notice is as follows.

   Copyright © 1993-1999 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
Permission to use, copy, modify, distribute,and license this software
and its documentation for any purpose is hereby granted, provided that
existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions.  No written agreement,
license, or royalty fee is required for any of the authorized uses.
This software is provided “AS IS” without express or implied warranty.

   The material has been adapted for use in Guile, with the author’s
permission.


File: guile.info,  Node: Class Definition,  Next: Instance Creation,  Prev: Copyright Notice,  Up: GOOPS

8.2 Class Definition
====================

A new class is defined with the ‘define-class’ syntax:

     (define-class CLASS (SUPERCLASS …)
        SLOT-DESCRIPTION …
        CLASS-OPTION …)

   CLASS is the class being defined.  The list of SUPERCLASSes specifies
which existing classes, if any, to inherit slots and properties from.
"Slots" hold per-instance(1) data, for instances of that class — like
“fields” or “member variables” in other object oriented systems.  Each
SLOT-DESCRIPTION gives the name of a slot and optionally some
“properties” of this slot; for example its initial value, the name of a
function which will access its value, and so on.  Class options, slot
descriptions and inheritance are discussed more below.

 -- syntax: define-class name (super …) slot-definition … class-option …
     Define a class called NAME that inherits from SUPERs, with direct
     slots defined by SLOT-DEFINITIONs and CLASS-OPTIONs.  The newly
     created class is bound to the variable name NAME in the current
     environment.

     Each SLOT-DEFINITION is either a symbol that names the slot or a
     list,

          (SLOT-NAME-SYMBOL . SLOT-OPTIONS)

     where SLOT-NAME-SYMBOL is a symbol and SLOT-OPTIONS is a list with
     an even number of elements.  The even-numbered elements of
     SLOT-OPTIONS (counting from zero) are slot option keywords; the
     odd-numbered elements are the corresponding values for those
     keywords.

     Each CLASS-OPTION is an option keyword and corresponding value.

   As an example, let us define a type for representing a complex number
in terms of two real numbers.(2)  This can be done with the following
class definition:

     (define-class <my-complex> (<number>)
        r i)

   This binds the variable ‘<my-complex>’ to a new class whose instances
will contain two slots.  These slots are called ‘r’ and ‘i’ and will
hold the real and imaginary parts of a complex number.  Note that this
class inherits from ‘<number>’, which is a predefined class.(3)

   Slot options are described in the next section.  The possible class
options are as follows.

 -- class option: #:metaclass metaclass
     The ‘#:metaclass’ class option specifies the metaclass of the class
     being defined.  METACLASS must be a class that inherits from
     ‘<class>’.  For the use of metaclasses, see *note Metaobjects and
     the Metaobject Protocol:: and *note Metaclasses::.

     If the ‘#:metaclass’ option is absent, GOOPS reuses or constructs a
     metaclass for the new class by calling ‘ensure-metaclass’ (*note
     ensure-metaclass: Class Definition Protocol.).

 -- class option: #:name name
     The ‘#:name’ class option specifies the new class’s name.  This
     name is used to identify the class whenever related objects - the
     class itself, its instances and its subclasses - are printed.

     If the ‘#:name’ option is absent, GOOPS uses the first argument to
     ‘define-class’ as the class name.

   ---------- Footnotes ----------

   (1) Usually — but see also the ‘#:allocation’ slot option.

   (2) Of course Guile already provides complex numbers, and ‘<complex>’
is in fact a predefined class in GOOPS; but the definition here is still
useful as an example.

   (3) ‘<number>’ is the direct superclass of the predefined class
‘<complex>’; ‘<complex>’ is the superclass of ‘<real>’, and ‘<real>’ is
the superclass of ‘<integer>’.


File: guile.info,  Node: Instance Creation,  Next: Slot Options,  Prev: Class Definition,  Up: GOOPS

8.3 Instance Creation and Slot Access
=====================================

An instance (or object) of a defined class can be created with ‘make’.
‘make’ takes one mandatory parameter, which is the class of the instance
to create, and a list of optional arguments that will be used to
initialize the slots of the new instance.  For instance the following
form

     (define c (make <my-complex>))

creates a new ‘<my-complex>’ object and binds it to the Scheme variable
‘c’.

 -- generic: make
 -- method: make (class <class>) initarg …
     Create and return a new instance of class CLASS, initialized using
     INITARG ....

     In theory, INITARG … can have any structure that is understood by
     whatever methods get applied when the ‘initialize’ generic function
     is applied to the newly allocated instance.

     In practice, specialized ‘initialize’ methods would normally call
     ‘(next-method)’, and so eventually the standard GOOPS ‘initialize’
     methods are applied.  These methods expect INITARGS to be a list
     with an even number of elements, where even-numbered elements
     (counting from zero) are keywords and odd-numbered elements are the
     corresponding values.

     GOOPS processes initialization argument keywords automatically for
     slots whose definition includes the ‘#:init-keyword’ option (*note
     init-keyword: Slot Options.).  Other keyword value pairs can only
     be processed by an ‘initialize’ method that is specialized for the
     new instance’s class.  Any unprocessed keyword value pairs are
     ignored.

 -- generic: make-instance
 -- method: make-instance (class <class>) initarg …
     ‘make-instance’ is an alias for ‘make’.

   The slots of the new complex number can be accessed using ‘slot-ref’
and ‘slot-set!’.  ‘slot-set!’ sets the value of an object slot and
‘slot-ref’ retrieves it.

     (slot-set! c 'r 10)
     (slot-set! c 'i 3)
     (slot-ref c 'r) ⇒ 10
     (slot-ref c 'i) ⇒ 3

   The ‘(oop goops describe)’ module provides a ‘describe’ function that
is useful for seeing all the slots of an object; it prints the slots and
their values to standard output.

     (describe c)
     ⊣
     #<<my-complex> 401d8638> is an instance of class <my-complex>
     Slots are:
          r = 10
          i = 3


File: guile.info,  Node: Slot Options,  Next: Slot Description Example,  Prev: Instance Creation,  Up: GOOPS

8.4 Slot Options
================

When specifying a slot (in a ‘(define-class …)’ form), various options
can be specified in addition to the slot’s name.  Each option is
specified by a keyword.  The list of possible keywords is as follows.

 -- slot option: #:init-value init-value
 -- slot option: #:init-form init-form
 -- slot option: #:init-thunk init-thunk
 -- slot option: #:init-keyword init-keyword
     These options provide various ways to specify how to initialize the
     slot’s value at instance creation time.

     INIT-VALUE specifies a fixed initial slot value (shared across all
     new instances of the class).

     INIT-THUNK specifies a thunk that will provide a default value for
     the slot.  The thunk is called when a new instance is created and
     should return the desired initial slot value.

     INIT-FORM specifies a form that, when evaluated, will return an
     initial value for the slot.  The form is evaluated each time that
     an instance of the class is created, in the lexical environment of
     the containing ‘define-class’ expression.

     INIT-KEYWORD specifies a keyword that can be used to pass an
     initial slot value to ‘make’ when creating a new instance.

     Note that, since an ‘init-value’ value is shared across all
     instances of a class, you should only use it when the initial value
     is an immutable value, like a constant.  If you want to initialize
     a slot with a fresh, independently mutable value, you should use
     ‘init-thunk’ or ‘init-form’ instead.  Consider the following
     example.

          (define-class <chbouib> ()
            (hashtab #:init-value (make-hash-table)))

     Here only one hash table is created and all instances of
     ‘<chbouib>’ have their ‘hashtab’ slot refer to it.  In order to
     have each instance of ‘<chbouib>’ refer to a new hash table, you
     should instead write:

          (define-class <chbouib> ()
            (hashtab #:init-thunk make-hash-table))

     or:

          (define-class <chbouib> ()
            (hashtab #:init-form (make-hash-table)))

     If more than one of these options is specified for the same slot,
     the order of precedence, highest first is

        • ‘#:init-keyword’, if INIT-KEYWORD is present in the options
          passed to ‘make’

        • ‘#:init-thunk’, ‘#:init-form’ or ‘#:init-value’.

     If the slot definition contains more than one initialization option
     of the same precedence, the later ones are ignored.  If a slot is
     not initialized at all, its value is unbound.

     In general, slots that are shared between more than one instance
     are only initialized at new instance creation time if the slot
     value is unbound at that time.  However, if the new instance
     creation specifies a valid init keyword and value for a shared
     slot, the slot is re-initialized regardless of its previous value.

     Note, however, that the power of GOOPS’ metaobject protocol means
     that everything written here may be customized or overridden for
     particular classes!  The slot initializations described here are
     performed by the least specialized method of the generic function
     ‘initialize’, whose signature is

          (define-method (initialize (object <object>) initargs) ...)

     The initialization of instances of any given class can be
     customized by defining a ‘initialize’ method that is specialized
     for that class, and the author of the specialized method may decide
     to call ‘next-method’ - which will result in a call to the next
     less specialized ‘initialize’ method - at any point within the
     specialized code, or maybe not at all.  In general, therefore, the
     initialization mechanisms described here may be modified or
     overridden by more specialized code, or may not be supported at all
     for particular classes.

 -- slot option: #:getter getter
 -- slot option: #:setter setter
 -- slot option: #:accessor accessor
     Given an object OBJ with slots named ‘foo’ and ‘bar’, it is always
     possible to read and write those slots by calling ‘slot-ref’ and
     ‘slot-set!’ with the relevant slot name; for example:

          (slot-ref OBJ 'foo)
          (slot-set! OBJ 'bar 25)

     The ‘#:getter’, ‘#:setter’ and ‘#:accessor’ options, if present,
     tell GOOPS to create generic function and method definitions that
     can be used to get and set the slot value more conveniently.
     GETTER specifies a generic function to which GOOPS will add a
     method for getting the slot value.  SETTER specifies a generic
     function to which GOOPS will add a method for setting the slot
     value.  ACCESSOR specifies an accessor to which GOOPS will add
     methods for both getting and setting the slot value.

     So if a class includes a slot definition like this:

          (c #:getter get-count #:setter set-count #:accessor count)

     GOOPS defines generic function methods such that the slot value can
     be referenced using either the getter or the accessor -

          (let ((current-count (get-count obj))) …)
          (let ((current-count (count obj))) …)

     - and set using either the setter or the accessor -

          (set-count obj (+ 1 current-count))
          (set! (count obj) (+ 1 current-count))

     Note that

        • with an accessor, the slot value is set using the generalized
          ‘set!’ syntax

        • in practice, it is unusual for a slot to use all three of
          these options: read-only, write-only and read-write slots
          would typically use only ‘#:getter’, ‘#:setter’ and
          ‘#:accessor’ options respectively.

     The binding of the specified names is done in the environment of
     the ‘define-class’ expression.  If the names are already bound (in
     that environment) to values that cannot be upgraded to generic
     functions, those values are overwritten when the ‘define-class’
     expression is evaluated.  For more detail, see *note
     ensure-generic: Generic Function Internals.

 -- slot option: #:allocation allocation
     The ‘#:allocation’ option tells GOOPS how to allocate storage for
     the slot.  Possible values for ALLOCATION are

        • ‘#:instance’

          Indicates that GOOPS should create separate storage for this
          slot in each new instance of the containing class (and its
          subclasses).  This is the default.

        • ‘#:class’

          Indicates that GOOPS should create storage for this slot that
          is shared by all instances of the containing class (and its
          subclasses).  In other words, a slot in class C with
          allocation ‘#:class’ is shared by all INSTANCEs for which
          ‘(is-a? INSTANCE C)’.  This permits defining a kind of global
          variable which can be accessed only by (in)direct instances of
          the class which defines the slot.

        • ‘#:each-subclass’

          Indicates that GOOPS should create storage for this slot that
          is shared by all _direct_ instances of the containing class,
          and that whenever a subclass of the containing class is
          defined, GOOPS should create a new storage for the slot that
          is shared by all _direct_ instances of the subclass.  In other
          words, a slot with allocation ‘#:each-subclass’ is shared by
          all instances with the same ‘class-of’.

        • ‘#:virtual’

          Indicates that GOOPS should not allocate storage for this
          slot.  The slot definition must also include the ‘#:slot-ref’
          and ‘#:slot-set!’ options to specify how to reference and set
          the value for this slot.  See the example below.

     Slot allocation options are processed when defining a new class by
     the generic function ‘compute-get-n-set’, which is specialized by
     the class’s metaclass.  Hence new types of slot allocation can be
     implemented by defining a new metaclass and a method for
     ‘compute-get-n-set’ that is specialized for the new metaclass.  For
     an example of how to do this, see *note Customizing Class
     Definition::.

 -- slot option: #:slot-ref getter
 -- slot option: #:slot-set! setter
     The ‘#:slot-ref’ and ‘#:slot-set!’ options must be specified if the
     slot allocation is ‘#:virtual’, and are ignored otherwise.

     GETTER should be a closure taking a single INSTANCE parameter that
     returns the current slot value.  SETTER should be a closure taking
     two parameters - INSTANCE and NEW-VAL - that sets the slot value to
     NEW-VAL.


File: guile.info,  Node: Slot Description Example,  Next: Methods and Generic Functions,  Prev: Slot Options,  Up: GOOPS

8.5 Illustrating Slot Description
=================================

To illustrate slot description, we can redefine the ‘<my-complex>’ class
seen before.  A definition could be:

     (define-class <my-complex> (<number>)
        (r #:init-value 0 #:getter get-r #:setter set-r! #:init-keyword #:r)
        (i #:init-value 0 #:getter get-i #:setter set-i! #:init-keyword #:i))

With this definition, the ‘r’ and ‘i’ slots are set to 0 by default, and
can be initialised to other values by calling ‘make’ with the ‘#:r’ and
‘#:i’ keywords.  Also the generic functions ‘get-r’, ‘set-r!’, ‘get-i’
and ‘set-i!’ are automatically defined to read and write the slots.

     (define c1 (make <my-complex> #:r 1 #:i 2))
     (get-r c1) ⇒ 1
     (set-r! c1 12)
     (get-r c1) ⇒ 12
     (define c2 (make <my-complex> #:r 2))
     (get-r c2) ⇒ 2
     (get-i c2) ⇒ 0

   Accessors can both read and write a slot.  So, another definition of
the ‘<my-complex>’ class, using the ‘#:accessor’ option, could be:

     (define-class <my-complex> (<number>)
        (r #:init-value 0 #:accessor real-part #:init-keyword #:r)
        (i #:init-value 0 #:accessor imag-part #:init-keyword #:i))

With this definition, the ‘r’ slot can be read with:
     (real-part c)
and set with:
     (set! (real-part c) new-value)

   Suppose now that we want to manipulate complex numbers with both
rectangular and polar coordinates.  One solution could be to have a
definition of complex numbers which uses one particular representation
and some conversion functions to pass from one representation to the
other.  A better solution is to use virtual slots, like this:

     (define-class <my-complex> (<number>)
        ;; True slots use rectangular coordinates
        (r #:init-value 0 #:accessor real-part #:init-keyword #:r)
        (i #:init-value 0 #:accessor imag-part #:init-keyword #:i)
        ;; Virtual slots access do the conversion
        (m #:accessor magnitude #:init-keyword #:magn
           #:allocation #:virtual
           #:slot-ref (lambda (o)
                       (let ((r (slot-ref o 'r)) (i (slot-ref o 'i)))
                         (sqrt (+ (* r r) (* i i)))))
           #:slot-set! (lambda (o m)
                         (let ((a (slot-ref o 'a)))
                           (slot-set! o 'r (* m (cos a)))
                           (slot-set! o 'i (* m (sin a))))))
        (a #:accessor angle #:init-keyword #:angle
           #:allocation #:virtual
           #:slot-ref (lambda (o)
                       (atan (slot-ref o 'i) (slot-ref o 'r)))
           #:slot-set! (lambda(o a)
                        (let ((m (slot-ref o 'm)))
                           (slot-set! o 'r (* m (cos a)))
                           (slot-set! o 'i (* m (sin a)))))))


   In this class definition, the magnitude ‘m’ and angle ‘a’ slots are
virtual, and are calculated, when referenced, from the normal (i.e.
‘#:allocation #:instance’) slots ‘r’ and ‘i’, by calling the function
defined in the relevant ‘#:slot-ref’ option.  Correspondingly, writing
‘m’ or ‘a’ leads to calling the function defined in the ‘#:slot-set!’
option.  Thus the following expression

     (slot-set! c 'a 3)

permits to set the angle of the ‘c’ complex number.

     (define c (make <my-complex> #:r 12 #:i 20))
     (real-part c) ⇒ 12
     (angle c) ⇒ 1.03037682652431
     (slot-set! c 'i 10)
     (set! (real-part c) 1)
     (describe c)
     ⊣
     #<<my-complex> 401e9b58> is an instance of class <my-complex>
     Slots are:
          r = 1
          i = 10
          m = 10.0498756211209
          a = 1.47112767430373

   Since initialization keywords have been defined for the four slots,
we can now define the standard Scheme primitives ‘make-rectangular’ and
‘make-polar’.

     (define make-rectangular
        (lambda (x y) (make <my-complex> #:r x #:i y)))

     (define make-polar
        (lambda (x y) (make <my-complex> #:magn x #:angle y)))


File: guile.info,  Node: Methods and Generic Functions,  Next: Inheritance,  Prev: Slot Description Example,  Up: GOOPS

8.6 Methods and Generic Functions
=================================

A GOOPS method is like a Scheme procedure except that it is specialized
for a particular set of argument classes, and will only be used when the
actual arguments in a call match the classes in the method definition.

     (define-method (+ (x <string>) (y <string>))
       (string-append x y))

     (+ "abc" "de") ⇒ "abcde"

   A method is not formally associated with any single class (as it is
in many other object oriented languages), because a method can be
specialized for a combination of several classes.  If you’ve studied
object orientation in non-Lispy languages, you may remember discussions
such as whether a method to stretch a graphical image around a surface
should be a method of the image class, with a surface as a parameter, or
a method of the surface class, with an image as a parameter.  In GOOPS
you’d just write

     (define-method (stretch (im <image>) (sf <surface>))
       ...)

and the question of which class the method is more associated with does
not need answering.

   There can simultaneously be several methods with the same name but
different sets of specializing argument classes; for example:

     (define-method (+ (x <string>) (y <string)) ...)
     (define-method (+ (x <matrix>) (y <matrix>)) ...)
     (define-method (+ (f <fish>) (b <bicycle>)) ...)
     (define-method (+ (a <foo>) (b <bar>) (c <baz>)) ...)

A generic function is a container for the set of such methods that a
program intends to use.

   If you look at a program’s source code, and see ‘(+ x y)’ somewhere
in it, conceptually what is happening is that the program at that point
calls a generic function (in this case, the generic function bound to
the identifier ‘+’).  When that happens, Guile works out which of the
generic function’s methods is the most appropriate for the arguments
that the function is being called with; then it evaluates the method’s
code with the arguments as formal parameters.  This happens every time
that a generic function call is evaluated — it isn’t assumed that a
given source code call will end up invoking the same method every time.

   Defining an identifier as a generic function is done with the
‘define-generic’ macro.  Definition of a new method is done with the
‘define-method’ macro.  Note that ‘define-method’ automatically does a
‘define-generic’ if the identifier concerned is not already a generic
function, so often an explicit ‘define-generic’ call is not needed.

 -- syntax: define-generic symbol
     Create a generic function with name SYMBOL and bind it to the
     variable SYMBOL.  If SYMBOL was previously bound to a Scheme
     procedure (or procedure-with-setter), the old procedure (and
     setter) is incorporated into the new generic function as its
     default procedure (and setter).  Any other previous value,
     including an existing generic function, is discarded and replaced
     by a new, empty generic function.

 -- syntax: define-method (generic parameter …) body …
     Define a method for the generic function or accessor GENERIC with
     parameters PARAMETERs and body BODY ....

     GENERIC is a generic function.  If GENERIC is a variable which is
     not yet bound to a generic function object, the expansion of
     ‘define-method’ will include a call to ‘define-generic’.  If
     GENERIC is ‘(setter GENERIC-WITH-SETTER)’, where
     GENERIC-WITH-SETTER is a variable which is not yet bound to a
     generic-with-setter object, the expansion will include a call to
     ‘define-accessor’.

     Each PARAMETER must be either a symbol or a two-element list
     ‘(SYMBOL CLASS)’.  The symbols refer to variables in the body forms
     that will be bound to the parameters supplied by the caller when
     calling this method.  The CLASSes, if present, specify the possible
     combinations of parameters to which this method can be applied.

     BODY … are the bodies of the method definition.

   ‘define-method’ expressions look a little like Scheme procedure
definitions of the form

     (define (name formals …) . body)

   The important difference is that each formal parameter, apart from
the possible “rest” argument, can be qualified by a class name: ‘FORMAL’
becomes ‘(FORMAL CLASS)’.  The meaning of this qualification is that the
method being defined will only be applicable in a particular generic
function invocation if the corresponding argument is an instance of
‘CLASS’ (or one of its subclasses).  If more than one of the formal
parameters is qualified in this way, then the method will only be
applicable if each of the corresponding arguments is an instance of its
respective qualifying class.

   Note that unqualified formal parameters act as though they are
qualified by the class ‘<top>’, which GOOPS uses to mean the superclass
of all valid Scheme types, including both primitive types and GOOPS
classes.

   For example, if a generic function method is defined with PARAMETERs
‘(s1 <square>)’ and ‘(n <number>)’, that method is only applicable to
invocations of its generic function that have two parameters where the
first parameter is an instance of the ‘<square>’ class and the second
parameter is a number.

* Menu:

* Accessors::
* Extending Primitives::
* Merging Generics::
* Next-method::                 
* Generic Function and Method Examples::                     
* Handling Invocation Errors::


File: guile.info,  Node: Accessors,  Next: Extending Primitives,  Up: Methods and Generic Functions

8.6.1 Accessors
---------------

An accessor is a generic function that can also be used with the
generalized ‘set!’ syntax (*note Procedures with Setters::).  Guile will
handle a call like

     (set! (accessor args…) value)

by calling the most specialized method of ‘accessor’ that matches the
classes of ‘args’ and ‘value’.  ‘define-accessor’ is used to bind an
identifier to an accessor.

 -- syntax: define-accessor symbol
     Create an accessor with name SYMBOL and bind it to the variable
     SYMBOL.  If SYMBOL was previously bound to a Scheme procedure (or
     procedure-with-setter), the old procedure (and setter) is
     incorporated into the new accessor as its default procedure (and
     setter).  Any other previous value, including an existing generic
     function or accessor, is discarded and replaced by a new, empty
     accessor.


File: guile.info,  Node: Extending Primitives,  Next: Merging Generics,  Prev: Accessors,  Up: Methods and Generic Functions

8.6.2 Extending Primitives
--------------------------

Many of Guile’s primitive procedures can be extended by giving them a
generic function definition that operates in conjunction with their
normal C-coded implementation.  When a primitive is extended in this
way, it behaves like a generic function with the C-coded implementation
as its default method.

   This extension happens automatically if a method is defined (by a
‘define-method’ call) for a variable whose current value is a primitive.
But it can also be forced by calling ‘enable-primitive-generic!’.

 -- primitive procedure: enable-primitive-generic! primitive
     Force the creation of a generic function definition for PRIMITIVE.

   Once the generic function definition for a primitive has been
created, it can be retrieved using ‘primitive-generic-generic’.

 -- primitive procedure: primitive-generic-generic primitive
     Return the generic function definition of PRIMITIVE.

     ‘primitive-generic-generic’ raises an error if PRIMITIVE is not a
     primitive with generic capability.


File: guile.info,  Node: Merging Generics,  Next: Next-method,  Prev: Extending Primitives,  Up: Methods and Generic Functions

8.6.3 Merging Generics
----------------------

GOOPS generic functions and accessors often have short, generic names.
For example, if a vector package provides an accessor for the X
coordinate of a vector, that accessor may just be called ‘x’.  It
doesn’t need to be called, for example, ‘vector:x’, because GOOPS will
work out, when it sees code like ‘(x OBJ)’, that the vector-specific
method of ‘x’ should be called if OBJ is a vector.

   That raises the question, though, of what happens when different
packages define a generic function with the same name.  Suppose we work
with a graphical package which needs to use two independent vector
packages for 2D and 3D vectors respectively.  If both packages export
‘x’, what does the code using those packages end up with?

   *note duplicate binding handlers: Creating Guile Modules. explains
how this is resolved for conflicting bindings in general.  For generics,
there is a special duplicates handler, ‘merge-generics’, which tells the
module system to merge generic functions with the same name.  Here is an
example:

     (define-module (math 2D-vectors)
       #:use-module (oop goops)
       #:export (x y ...))

     (define-module (math 3D-vectors)
       #:use-module (oop goops)
       #:export (x y z ...))

     (define-module (my-module)
       #:use-module (oop goops)
       #:use-module (math 2D-vectors)
       #:use-module (math 3D-vectors)
       #:duplicates (merge-generics))

   The generic function ‘x’ in ‘(my-module)’ will now incorporate all of
the methods of ‘x’ from both imported modules.

   To be precise, there will now be three distinct generic functions
named ‘x’: ‘x’ in ‘(math 2D-vectors)’, ‘x’ in ‘(math 3D-vectors)’, and
‘x’ in ‘(my-module)’; and these functions share their methods in an
interesting and dynamic way.

   To explain, let’s call the imported generic functions (in ‘(math
2D-vectors)’ and ‘(math 3D-vectors)’) the "ancestors", and the merged
generic function (in ‘(my-module)’), the "descendant".  The general rule
is that for any generic function G, the applicable methods are selected
from the union of the methods of G’s descendant functions, the methods
of G itself and the methods of G’s ancestor functions.

   Thus ancestor functions effectively share methods with their
descendants, and vice versa.  In the example above, ‘x’ in ‘(math
2D-vectors)’ will share the methods of ‘x’ in ‘(my-module)’ and vice
versa.(1)  Sharing is dynamic, so adding another new method to a
descendant implies adding it to that descendant’s ancestors too.

   ---------- Footnotes ----------

   (1) But note that ‘x’ in ‘(math 2D-vectors)’ doesn’t share methods
with ‘x’ in ‘(math 3D-vectors)’, so modularity is still preserved.


File: guile.info,  Node: Next-method,  Next: Generic Function and Method Examples,  Prev: Merging Generics,  Up: Methods and Generic Functions

8.6.4 Next-method
-----------------

When you call a generic function, with a particular set of arguments,
GOOPS builds a list of all the methods that are applicable to those
arguments and orders them by how closely the method definitions match
the actual argument types.  It then calls the method at the top of this
list.  If the selected method’s code wants to call on to the next method
in this list, it can do so by using ‘next-method’.

     (define-method (Test (a <integer>)) (cons 'integer (next-method)))
     (define-method (Test (a <number>))  (cons 'number  (next-method)))
     (define-method (Test a)             (list 'top))

   With these definitions,

     (Test 1)   ⇒ (integer number top)
     (Test 1.0) ⇒ (number top)
     (Test #t)  ⇒ (top)

   ‘next-method’ is always called as just ‘(next-method)’.  The
arguments for the next method call are always implicit, and always the
same as for the original method call.

   If you want to call on to a method with the same name but with a
different set of arguments (as you might with overloaded methods in C++,
for example), you do not use ‘next-method’, but instead simply write the
new call as usual:

     (define-method (Test (a <number>) min max)
       (if (and (>= a min) (<= a max))
           (display "Number is in range\n"))
       (Test a))

     (Test 2 1 10)
     ⊣
     Number is in range
     ⇒
     (integer number top)

   (You should be careful in this case that the ‘Test’ calls do not lead
to an infinite recursion, but this consideration is just the same as in
Scheme code in general.)


File: guile.info,  Node: Generic Function and Method Examples,  Next: Handling Invocation Errors,  Prev: Next-method,  Up: Methods and Generic Functions

8.6.5 Generic Function and Method Examples
------------------------------------------

Consider the following definitions:

     (define-generic G)
     (define-method (G (a <integer>) b) 'integer)
     (define-method (G (a <real>) b) 'real)
     (define-method (G a b) 'top)

   The ‘define-generic’ call defines G as a generic function.  The three
next lines define methods for G.  Each method uses a sequence of
"parameter specializers" that specify when the given method is
applicable.  A specializer permits to indicate the class a parameter
must belong to (directly or indirectly) to be applicable.  If no
specializer is given, the system defaults it to ‘<top>’.  Thus, the
first method definition is equivalent to

     (define-method (G (a <integer>) (b <top>)) 'integer)

   Now, let’s look at some possible calls to the generic function G:

     (G 2 3)    ⇒ integer
     (G 2 #t)   ⇒ integer
     (G 1.2 'a) ⇒ real
     (G #t #f)  ⇒ top
     (G 1 2 3)  ⇒ error (since no method exists for 3 parameters)

   The methods above use only one specializer per parameter list.  But
in general, any or all of a method’s parameters may be specialized.
Suppose we define now:

     (define-method (G (a <integer>) (b <number>))  'integer-number)
     (define-method (G (a <integer>) (b <real>))    'integer-real)
     (define-method (G (a <integer>) (b <integer>)) 'integer-integer)
     (define-method (G a (b <number>))              'top-number)

With these definitions:

     (G 1 2)   ⇒ integer-integer
     (G 1 1.0) ⇒ integer-real
     (G 1 #t)  ⇒ integer
     (G 'a 1)  ⇒ top-number

   As a further example we shall continue to define operations on the
‘<my-complex>’ class.  Suppose that we want to use it to implement
complex numbers completely.  For instance a definition for the addition
of two complex numbers could be

     (define-method (new-+ (a <my-complex>) (b <my-complex>))
       (make-rectangular (+ (real-part a) (real-part b))
                         (+ (imag-part a) (imag-part b))))

   To be sure that the ‘+’ used in the method ‘new-+’ is the standard
addition we can do:

     (define-generic new-+)

     (let ((+ +))
       (define-method (new-+ (a <my-complex>) (b <my-complex>))
         (make-rectangular (+ (real-part a) (real-part b))
                           (+ (imag-part a) (imag-part b)))))

   The ‘define-generic’ ensures here that ‘new-+’ will be defined in the
global environment.  Once this is done, we can add methods to the
generic function ‘new-+’ which make a closure on the ‘+’ symbol.  A
complete writing of the ‘new-+’ methods is shown in *note Figure 8.1:
fig:newplus.

     (define-generic new-+)

     (let ((+ +))

       (define-method (new-+ (a <real>) (b <real>)) (+ a b))

       (define-method (new-+ (a <real>) (b <my-complex>))
         (make-rectangular (+ a (real-part b)) (imag-part b)))

       (define-method (new-+ (a <my-complex>) (b <real>))
         (make-rectangular (+ (real-part a) b) (imag-part a)))

       (define-method (new-+ (a <my-complex>) (b <my-complex>))
         (make-rectangular (+ (real-part a) (real-part b))
                           (+ (imag-part a) (imag-part b))))

       (define-method (new-+ (a <number>))  a)

       (define-method (new-+) 0)

       (define-method (new-+ . args)
         (new-+ (car args)
           (apply new-+ (cdr args)))))

     (set! + new-+)

Figure 8.1: Extending ‘+’ to handle complex numbers

   We take advantage here of the fact that generic function are not
obliged to have a fixed number of parameters.  The four first methods
implement dyadic addition.  The fifth method says that the addition of a
single element is this element itself.  The sixth method says that using
the addition with no parameter always return 0 (as is also true for the
primitive ‘+’).  The last method takes an arbitrary number of
parameters(1).  This method acts as a kind of ‘reduce’: it calls the
dyadic addition on the _car_ of the list and on the result of applying
it on its rest.  To finish, the ‘set!’ permits to redefine the ‘+’
symbol to our extended addition.

   To conclude our implementation (integration?)  of complex numbers, we
could redefine standard Scheme predicates in the following manner:

     (define-method (complex? c <my-complex>) #t)
     (define-method (complex? c)           #f)

     (define-method (number? n <number>) #t)
     (define-method (number? n)          #f)
     …

   Standard primitives in which complex numbers are involved could also
be redefined in the same manner.

   ---------- Footnotes ----------

   (1) The parameter list for a ‘define-method’ follows the conventions
used for Scheme procedures.  In particular it can use the dot notation
or a symbol to denote an arbitrary number of parameters


File: guile.info,  Node: Handling Invocation Errors,  Prev: Generic Function and Method Examples,  Up: Methods and Generic Functions

8.6.6 Handling Invocation Errors
--------------------------------

If a generic function is invoked with a combination of parameters for
which there is no applicable method, GOOPS raises an error.

 -- generic: no-method
 -- method: no-method (gf <generic>) args
     When an application invokes a generic function, and no methods at
     all have been defined for that generic function, GOOPS calls the
     ‘no-method’ generic function.  The default method calls
     ‘goops-error’ with an appropriate message.

 -- generic: no-applicable-method
 -- method: no-applicable-method (gf <generic>) args
     When an application applies a generic function to a set of
     arguments, and no methods have been defined for those argument
     types, GOOPS calls the ‘no-applicable-method’ generic function.
     The default method calls ‘goops-error’ with an appropriate message.

 -- generic: no-next-method
 -- method: no-next-method (gf <generic>) args
     When a generic function method calls ‘(next-method)’ to invoke the
     next less specialized method for that generic function, and no less
     specialized methods have been defined for the current generic
     function arguments, GOOPS calls the ‘no-next-method’ generic
     function.  The default method calls ‘goops-error’ with an
     appropriate message.


File: guile.info,  Node: Inheritance,  Next: Introspection,  Prev: Methods and Generic Functions,  Up: GOOPS

8.7 Inheritance
===============

Here are some class definitions to help illustrate inheritance:

     (define-class A () a)
     (define-class B () b)
     (define-class C () c)
     (define-class D (A B) d a)
     (define-class E (A C) e c)
     (define-class F (D E) f)

   ‘A’, ‘B’, ‘C’ have a null list of superclasses.  In this case, the
system will replace the null list by a list which only contains
‘<object>’, the root of all the classes defined by ‘define-class’.  ‘D’,
‘E’, ‘F’ use multiple inheritance: each class inherits from two
previously defined classes.  Those class definitions define a hierarchy
which is shown in *note Figure 8.2: fig:hier.  In this figure, the class
‘<top>’ is also shown; this class is the superclass of all Scheme
objects.  In particular, ‘<top>’ is the superclass of all standard
Scheme types.

          <top>
          / \\\_____________________
         /   \\___________          \
        /     \           \          \
    <object>  <pair>  <procedure>  <number>
    /  |  \                           |
   /   |   \                          |
  A    B    C                      <complex>
  |\__/__   |                         |
   \ /   \ /                          |
    D     E                         <real>
     \   /                            |
       F                              |
                                   <integer>

Figure 8.2: A class hierarchy.

   When a class has superclasses, its set of slots is calculated by
taking the union of its own slots and those of all its superclasses.
Thus each instance of D will have three slots, ‘a’, ‘b’ and ‘d’).  The
slots of a class can be discovered using the ‘class-slots’ primitive.
For instance,

     (class-slots A) ⇒ ((a))
     (class-slots E) ⇒ ((a) (e) (c))
     (class-slots F) ⇒ ((e) (c) (b) (d) (a) (f))

The ordering of the returned slots is not significant.

* Menu:

* Class Precedence List::
* Sorting Methods::


File: guile.info,  Node: Class Precedence List,  Next: Sorting Methods,  Up: Inheritance

8.7.1 Class Precedence List
---------------------------

What happens when a class inherits from two or more superclasses that
have a slot with the same name but incompatible definitions — for
example, different init values or slot allocations?  We need a rule for
deciding which slot definition the derived class ends up with, and this
rule is provided by the class’s "Class Precedence List".(1)

   Another problem arises when invoking a generic function, and there is
more than one method that could apply to the call arguments.  Here we
need a way of ordering the applicable methods, so that Guile knows which
method to use first, which to use next if that method calls
‘next-method’, and so on.  One of the ingredients for this ordering is
determining, for each given call argument, which of the specializing
classes, from each applicable method’s definition, is the most specific
for that argument; and here again the class precedence list helps.

   If inheritance was restricted such that each class could only have
one superclass — which is known as "single" inheritance — class ordering
would be easy.  The rule would be simply that a subclass is considered
more specific than its superclass.

   With multiple inheritance, ordering is less obvious, and we have to
impose an arbitrary rule to determine precedence.  Suppose we have

     (define-class X ()
        (x #:init-value 1))

     (define-class Y ()
        (x #:init-value 2))

     (define-class Z (X Y)
        (…))

Clearly the ‘Z’ class is more specific than ‘X’ or ‘Y’, for instances of
‘Z’.  But which is more specific out of ‘X’ and ‘Y’ — and hence, for the
definitions above, which ‘#:init-value’ will take effect when creating
an instance of ‘Z’?  The rule in GOOPS is that the superclasses listed
earlier are more specific than those listed later.  Hence ‘X’ is more
specific than ‘Y’, and the ‘#:init-value’ for slot ‘x’ in instances of
‘Z’ will be 1.

   Hence there is a linear ordering for a class and all its
superclasses, from most specific to least specific, and this ordering is
called the Class Precedence List of the class.

   In fact the rules above are not quite enough to always determine a
unique order, but they give an idea of how things work.  For example,
for the ‘F’ class shown in *note Figure 8.2: fig:hier, the class
precedence list is

     (f d e a c b <object> <top>)

In cases where there is any ambiguity (like this one), it is a bad idea
for programmers to rely on exactly what the order is.  If the order for
some superclasses is important, it can be expressed directly in the
class definition.

   The precedence list of a class can be obtained by calling
‘class-precedence-list’.  This function returns a ordered list whose
first element is the most specific class.  For instance:

     (class-precedence-list B) ⇒ (#<<class> B 401b97c8>
                                          #<<class> <object> 401e4a10>
                                          #<<class> <top> 4026a9d8>)

Or for a more immediately readable result:

     (map class-name (class-precedence-list B)) ⇒ (B <object> <top>)

   ---------- Footnotes ----------

   (1) This section is an adaptation of material from Jeff Dalton’s
(J.Dalton@ed.ac.uk) ‘Brief introduction to CLOS’


File: guile.info,  Node: Sorting Methods,  Prev: Class Precedence List,  Up: Inheritance

8.7.2 Sorting Methods
---------------------

Now, with the idea of the class precedence list, we can state precisely
how the possible methods are sorted when more than one of the methods of
a generic function are applicable to the call arguments.

   The rules are that
   • the applicable methods are sorted in order of specificity, and the
     most specific method is used first, then the next if that method
     calls ‘next-method’, and so on

   • a method M1 is more specific than another method M2 if the first
     specializing class that differs, between the definitions of M1 and
     M2, is more specific, in M1’s definition, for the corresponding
     actual call argument, than the specializing class in M2’s
     definition

   • a class C1 is more specific than another class C2, for an object of
     actual class C, if C1 comes before C2 in C’s class precedence list.


File: guile.info,  Node: Introspection,  Next: GOOPS Error Handling,  Prev: Inheritance,  Up: GOOPS

8.8 Introspection
=================

"Introspection", or "reflection", means being able to obtain information
dynamically about GOOPS objects.  It is perhaps best illustrated by
considering an object oriented language that does not provide any
introspection, namely C++.

   Nothing in C++ allows a running program to obtain answers to the
following types of question:

   • What are the data members of this object or class?

   • What classes does this class inherit from?

   • Is this method call virtual or non-virtual?

   • If I invoke ‘Employee::adjustHoliday()’, what class contains the
     ‘adjustHoliday()’ method that will be applied?

   In C++, answers to such questions can only be determined by looking
at the source code, if you have access to it.  GOOPS, on the other hand,
includes procedures that allow answers to these questions — or their
GOOPS equivalents — to be obtained dynamically, at run time.

* Menu:

* Classes::
* Instances::
* Slots::
* Generic Functions::
* Accessing Slots::


File: guile.info,  Node: Classes,  Next: Instances,  Up: Introspection

8.8.1 Classes
-------------

A GOOPS class is itself an instance of the ‘<class>’ class, or of a
subclass of ‘<class>’.  The definition of the ‘<class>’ class has slots
that are used to describe the properties of a class, including the
following.

 -- primitive procedure: class-name class
     Return the name of class CLASS.  This is the value of CLASS’s
     ‘name’ slot.

 -- primitive procedure: class-direct-supers class
     Return a list containing the direct superclasses of CLASS.  This is
     the value of CLASS’s ‘direct-supers’ slot.

 -- primitive procedure: class-direct-slots class
     Return a list containing the slot definitions of the direct slots
     of CLASS.  This is the value of CLASS’s ‘direct-slots’ slot.

 -- primitive procedure: class-direct-subclasses class
     Return a list containing the direct subclasses of CLASS.  This is
     the value of CLASS’s ‘direct-subclasses’ slot.

 -- primitive procedure: class-direct-methods class
     Return a list of all the generic function methods that use CLASS as
     a formal parameter specializer.  This is the value of CLASS’s
     ‘direct-methods’ slot.

 -- primitive procedure: class-precedence-list class
     Return the class precedence list for class CLASS (*note Class
     Precedence List::).  This is the value of CLASS’s ‘cpl’ slot.

 -- primitive procedure: class-slots class
     Return a list containing the slot definitions for all CLASS’s
     slots, including any slots that are inherited from superclasses.
     This is the value of CLASS’s ‘slots’ slot.

 -- procedure: class-subclasses class
     Return a list of all subclasses of CLASS.

 -- procedure: class-methods class
     Return a list of all methods that use CLASS or a subclass of CLASS
     as one of its formal parameter specializers.


File: guile.info,  Node: Instances,  Next: Slots,  Prev: Classes,  Up: Introspection

8.8.2 Instances
---------------

 -- primitive procedure: class-of value
     Return the GOOPS class of any Scheme VALUE.

 -- primitive procedure: instance? object
     Return ‘#t’ if OBJECT is any GOOPS instance, otherwise ‘#f’.

 -- procedure: is-a? object class
     Return ‘#t’ if OBJECT is an instance of CLASS or one of its
     subclasses.

   You can use the ‘is-a?’ predicate to ask whether any given value
belongs to a given class, or ‘class-of’ to discover the class of a given
value.  Note that when GOOPS is loaded (by code using the ‘(oop goops)’
module) built-in classes like ‘<string>’, ‘<list>’ and ‘<number>’ are
automatically set up, corresponding to all Guile Scheme types.

     (is-a? 2.3 <number>) ⇒ #t
     (is-a? 2.3 <real>) ⇒ #t
     (is-a? 2.3 <string>) ⇒ #f
     (is-a? '("a" "b") <string>) ⇒ #f
     (is-a? '("a" "b") <list>) ⇒ #t
     (is-a? (car '("a" "b")) <string>) ⇒ #t
     (is-a? <string> <class>) ⇒ #t
     (is-a? <class> <string>) ⇒ #f

     (class-of 2.3) ⇒ #<<class> <real> 908c708>
     (class-of #(1 2 3)) ⇒ #<<class> <vector> 908cd20>
     (class-of <string>) ⇒ #<<class> <class> 8bd3e10>
     (class-of <class>) ⇒ #<<class> <class> 8bd3e10>


File: guile.info,  Node: Slots,  Next: Generic Functions,  Prev: Instances,  Up: Introspection

8.8.3 Slots
-----------

 -- procedure: class-slot-definition class slot-name
     Return the slot definition for the slot named SLOT-NAME in class
     CLASS.  SLOT-NAME should be a symbol.

 -- procedure: slot-definition-name slot-def
     Extract and return the slot name from SLOT-DEF.

 -- procedure: slot-definition-options slot-def
     Extract and return the slot options from SLOT-DEF.

 -- procedure: slot-definition-allocation slot-def
     Extract and return the slot allocation option from SLOT-DEF.  This
     is the value of the ‘#:allocation’ keyword (*note allocation: Slot
     Options.), or ‘#:instance’ if the ‘#:allocation’ keyword is absent.

 -- procedure: slot-definition-getter slot-def
     Extract and return the slot getter option from SLOT-DEF.  This is
     the value of the ‘#:getter’ keyword (*note getter: Slot Options.),
     or ‘#f’ if the ‘#:getter’ keyword is absent.

 -- procedure: slot-definition-setter slot-def
     Extract and return the slot setter option from SLOT-DEF.  This is
     the value of the ‘#:setter’ keyword (*note setter: Slot Options.),
     or ‘#f’ if the ‘#:setter’ keyword is absent.

 -- procedure: slot-definition-accessor slot-def
     Extract and return the slot accessor option from SLOT-DEF.  This is
     the value of the ‘#:accessor’ keyword (*note accessor: Slot
     Options.), or ‘#f’ if the ‘#:accessor’ keyword is absent.

 -- procedure: slot-definition-init-value slot-def
     Extract and return the slot init-value option from SLOT-DEF.  This
     is the value of the ‘#:init-value’ keyword (*note init-value: Slot
     Options.), or the unbound value if the ‘#:init-value’ keyword is
     absent.

 -- procedure: slot-definition-init-form slot-def
     Extract and return the slot init-form option from SLOT-DEF.  This
     is the value of the ‘#:init-form’ keyword (*note init-form: Slot
     Options.), or the unbound value if the ‘#:init-form’ keyword is
     absent.

 -- procedure: slot-definition-init-thunk slot-def
     Extract and return the slot init-thunk option from SLOT-DEF.  This
     is the value of the ‘#:init-thunk’ keyword (*note init-thunk: Slot
     Options.), or ‘#f’ if the ‘#:init-thunk’ keyword is absent.

 -- procedure: slot-definition-init-keyword slot-def
     Extract and return the slot init-keyword option from SLOT-DEF.
     This is the value of the ‘#:init-keyword’ keyword (*note
     init-keyword: Slot Options.), or ‘#f’ if the ‘#:init-keyword’
     keyword is absent.

 -- procedure: slot-init-function class slot-name
     Return the initialization function for the slot named SLOT-NAME in
     class CLASS.  SLOT-NAME should be a symbol.

     The returned initialization function incorporates the effects of
     the standard ‘#:init-thunk’, ‘#:init-form’ and ‘#:init-value’ slot
     options.  These initializations can be overridden by the
     ‘#:init-keyword’ slot option or by a specialized ‘initialize’
     method, so, in general, the function returned by
     ‘slot-init-function’ may be irrelevant.  For a fuller discussion,
     see *note init-value: Slot Options.


File: guile.info,  Node: Generic Functions,  Next: Accessing Slots,  Prev: Slots,  Up: Introspection

8.8.4 Generic Functions
-----------------------

A generic function is an instance of the ‘<generic>’ class, or of a
subclass of ‘<generic>’.  The definition of the ‘<generic>’ class has
slots that are used to describe the properties of a generic function.

 -- primitive procedure: generic-function-name gf
     Return the name of generic function GF.

 -- primitive procedure: generic-function-methods gf
     Return a list of the methods of generic function GF.  This is the
     value of GF’s ‘methods’ slot.

   Similarly, a method is an instance of the ‘<method>’ class, or of a
subclass of ‘<method>’; and the definition of the ‘<method>’ class has
slots that are used to describe the properties of a method.

 -- primitive procedure: method-generic-function method
     Return the generic function that METHOD belongs to.  This is the
     value of METHOD’s ‘generic-function’ slot.

 -- primitive procedure: method-specializers method
     Return a list of METHOD’s formal parameter specializers .  This is
     the value of METHOD’s ‘specializers’ slot.

 -- primitive procedure: method-procedure method
     Return the procedure that implements METHOD.  This is the value of
     METHOD’s ‘procedure’ slot.

 -- generic: method-source
 -- method: method-source (m <method>)
     Return an expression that prints to show the definition of method
     M.

          (define-generic cube)

          (define-method (cube (n <number>))
            (* n n n))

          (map method-source (generic-function-methods cube))
          ⇒
          ((method ((n <number>)) (* n n n)))


File: guile.info,  Node: Accessing Slots,  Prev: Generic Functions,  Up: Introspection

8.8.5 Accessing Slots
---------------------

Any slot, regardless of its allocation, can be queried, referenced and
set using the following four primitive procedures.

 -- primitive procedure: slot-exists? obj slot-name
     Return ‘#t’ if OBJ has a slot with name SLOT-NAME, otherwise ‘#f’.

 -- primitive procedure: slot-bound? obj slot-name
     Return ‘#t’ if the slot named SLOT-NAME in OBJ has a value,
     otherwise ‘#f’.

     ‘slot-bound?’ calls the generic function ‘slot-missing’ if OBJ does
     not have a slot called SLOT-NAME (*note slot-missing: Accessing
     Slots.).

 -- primitive procedure: slot-ref obj slot-name
     Return the value of the slot named SLOT-NAME in OBJ.

     ‘slot-ref’ calls the generic function ‘slot-missing’ if OBJ does
     not have a slot called SLOT-NAME (*note slot-missing: Accessing
     Slots.).

     ‘slot-ref’ calls the generic function ‘slot-unbound’ if the named
     slot in OBJ does not have a value (*note slot-unbound: Accessing
     Slots.).

 -- primitive procedure: slot-set! obj slot-name value
     Set the value of the slot named SLOT-NAME in OBJ to VALUE.

     ‘slot-set!’ calls the generic function ‘slot-missing’ if OBJ does
     not have a slot called SLOT-NAME (*note slot-missing: Accessing
     Slots.).

   GOOPS stores information about slots in classes.  Internally, all of
these procedures work by looking up the slot definition for the slot
named SLOT-NAME in the class ‘(class-of OBJ)’, and then using the slot
definition’s “getter” and “setter” closures to get and set the slot
value.

   The next four procedures differ from the previous ones in that they
take the class as an explicit argument, rather than assuming ‘(class-of
OBJ)’.  Therefore they allow you to apply the “getter” and “setter”
closures of a slot definition in one class to an instance of a different
class.

 -- primitive procedure: slot-exists-using-class? class obj slot-name
     Return ‘#t’ if CLASS has a slot definition for a slot with name
     SLOT-NAME, otherwise ‘#f’.

 -- primitive procedure: slot-bound-using-class? class obj slot-name
     Return ‘#t’ if applying ‘slot-ref-using-class’ to the same
     arguments would call the generic function ‘slot-unbound’, otherwise
     ‘#f’.

     ‘slot-bound-using-class?’ calls the generic function ‘slot-missing’
     if CLASS does not have a slot definition for a slot called
     SLOT-NAME (*note slot-missing: Accessing Slots.).

 -- primitive procedure: slot-ref-using-class class obj slot-name
     Apply the “getter” closure for the slot named SLOT-NAME in CLASS to
     OBJ, and return its result.

     ‘slot-ref-using-class’ calls the generic function ‘slot-missing’ if
     CLASS does not have a slot definition for a slot called SLOT-NAME
     (*note slot-missing: Accessing Slots.).

     ‘slot-ref-using-class’ calls the generic function ‘slot-unbound’ if
     the application of the “getter” closure to OBJ returns an unbound
     value (*note slot-unbound: Accessing Slots.).

 -- primitive procedure: slot-set-using-class! class obj slot-name value
     Apply the “setter” closure for the slot named SLOT-NAME in CLASS to
     OBJ and VALUE.

     ‘slot-set-using-class!’ calls the generic function ‘slot-missing’
     if CLASS does not have a slot definition for a slot called
     SLOT-NAME (*note slot-missing: Accessing Slots.).

   Slots whose allocation is per-class rather than per-instance can be
referenced and set without needing to specify any particular instance.

 -- procedure: class-slot-ref class slot-name
     Return the value of the slot named SLOT-NAME in class CLASS.  The
     named slot must have ‘#:class’ or ‘#:each-subclass’ allocation
     (*note allocation: Slot Options.).

     If there is no such slot with ‘#:class’ or ‘#:each-subclass’
     allocation, ‘class-slot-ref’ calls the ‘slot-missing’ generic
     function with arguments CLASS and SLOT-NAME.  Otherwise, if the
     slot value is unbound, ‘class-slot-ref’ calls the ‘slot-unbound’
     generic function, with the same arguments.

 -- procedure: class-slot-set! class slot-name value
     Set the value of the slot named SLOT-NAME in class CLASS to VALUE.
     The named slot must have ‘#:class’ or ‘#:each-subclass’ allocation
     (*note allocation: Slot Options.).

     If there is no such slot with ‘#:class’ or ‘#:each-subclass’
     allocation, ‘class-slot-ref’ calls the ‘slot-missing’ generic
     function with arguments CLASS and SLOT-NAME.

   When a ‘slot-ref’ or ‘slot-set!’ call specifies a non-existent slot
name, or tries to reference a slot whose value is unbound, GOOPS calls
one of the following generic functions.

 -- generic: slot-missing
 -- method: slot-missing (class <class>) slot-name
 -- method: slot-missing (class <class>) (object <object>) slot-name
 -- method: slot-missing (class <class>) (object <object>) slot-name
          value
     When an application attempts to reference or set a class or
     instance slot by name, and the slot name is invalid for the
     specified CLASS or OBJECT, GOOPS calls the ‘slot-missing’ generic
     function.

     The default methods all call ‘goops-error’ with an appropriate
     message.

 -- generic: slot-unbound
 -- method: slot-unbound (object <object>)
 -- method: slot-unbound (class <class>) slot-name
 -- method: slot-unbound (class <class>) (object <object>) slot-name
     When an application attempts to reference a class or instance slot,
     and the slot’s value is unbound, GOOPS calls the ‘slot-unbound’
     generic function.

     The default methods all call ‘goops-error’ with an appropriate
     message.


File: guile.info,  Node: GOOPS Error Handling,  Next: GOOPS Object Miscellany,  Prev: Introspection,  Up: GOOPS

8.9 Error Handling
==================

The procedure ‘goops-error’ is called to raise an appropriate error by
the default methods of the following generic functions:

   • ‘slot-missing’ (*note slot-missing: Accessing Slots.)

   • ‘slot-unbound’ (*note slot-unbound: Accessing Slots.)

   • ‘no-method’ (*note no-method: Handling Invocation Errors.)

   • ‘no-applicable-method’ (*note no-applicable-method: Handling
     Invocation Errors.)

   • ‘no-next-method’ (*note no-next-method: Handling Invocation
     Errors.)

   If you customize these functions for particular classes or
metaclasses, you may still want to use ‘goops-error’ to signal any error
conditions that you detect.

 -- procedure: goops-error format-string arg …
     Raise an error with key ‘goops-error’ and error message constructed
     from FORMAT-STRING and ARG ....  Error message formatting is as
     done by ‘scm-error’.


File: guile.info,  Node: GOOPS Object Miscellany,  Next: The Metaobject Protocol,  Prev: GOOPS Error Handling,  Up: GOOPS

8.10 GOOPS Object Miscellany
============================

Here we cover some points about GOOPS objects that aren’t substantial
enough to merit sections on their own.

Object Equality
---------------

When GOOPS is loaded, ‘eqv?’, ‘equal?’ and ‘=’ become generic functions,
and you can define methods for them, specialized for your own classes,
so as to control what the various kinds of equality mean for your
classes.

   For example, the ‘assoc’ procedure, for looking up an entry in an
alist, is specified as using ‘equal?’ to determine when the car of an
entry in the alist is the same as the key parameter that ‘assoc’ is
called with.  Hence, if you had defined a new class, and wanted to use
instances of that class as the keys in an alist, you could define a
method for ‘equal?’, for your class, to control ‘assoc’’s lookup
precisely.

Cloning Objects
---------------

 -- generic: shallow-clone
 -- method: shallow-clone (self <object>)
     Return a “shallow” clone of SELF.  The default method makes a
     shallow clone by allocating a new instance and copying slot values
     from self to the new instance.  Each slot value is copied either as
     an immediate value or by reference.

 -- generic: deep-clone
 -- method: deep-clone (self <object>)
     Return a “deep” clone of SELF.  The default method makes a deep
     clone by allocating a new instance and copying or cloning slot
     values from self to the new instance.  If a slot value is an
     instance (satisfies ‘instance?’), it is cloned by calling
     ‘deep-clone’ on that value.  Other slot values are copied either as
     immediate values or by reference.

Write and Display
-----------------

 -- primitive generic: write object port
 -- primitive generic: display object port
     When GOOPS is loaded, ‘write’ and ‘display’ become generic
     functions with special methods for printing

        • objects - instances of the class ‘<object>’

        • foreign objects - instances of the class ‘<foreign-object>’

        • classes - instances of the class ‘<class>’

        • generic functions - instances of the class ‘<generic>’

        • methods - instances of the class ‘<method>’.

     ‘write’ and ‘display’ print non-GOOPS values in the same way as the
     Guile primitive ‘write’ and ‘display’ functions.

   In addition to the cases mentioned, you can of course define ‘write’
and ‘display’ methods for your own classes, to customize how instances
of those classes are printed.


File: guile.info,  Node: The Metaobject Protocol,  Next: Redefining a Class,  Prev: GOOPS Object Miscellany,  Up: GOOPS

8.11 The Metaobject Protocol
============================

At this point, we’ve said about as much as can be said about GOOPS
without having to confront the idea of the metaobject protocol.  There
are a couple more topics that could be discussed in isolation first —
class redefinition, and changing the class of existing instances — but
in practice developers using them will be advanced enough to want to
understand the metaobject protocol too, and will probably be using the
protocol to customize exactly what happens during these events.

   So let’s plunge in.  GOOPS is based on a “metaobject protocol” (aka
“MOP”) derived from the ones used in CLOS (the Common Lisp Object
System), tiny-clos (a small Scheme implementation of a subset of CLOS
functionality) and STKlos.

   The MOP underlies many possible GOOPS customizations — such as
defining an ‘initialize’ method to customize the initialization of
instances of an application-defined class — and an understanding of the
MOP makes it much easier to explain such customizations in a precise
way.  And at a deeper level, understanding the MOP is a key part of
understanding GOOPS, and of taking full advantage of GOOPS’ power, by
customizing the behaviour of GOOPS itself.

* Menu:

* Metaobjects and the Metaobject Protocol::
* Metaclasses::
* MOP Specification::
* Instance Creation Protocol::
* Class Definition Protocol::
* Customizing Class Definition::
* Method Definition::
* Method Definition Internals::
* Generic Function Internals::
* Generic Function Invocation::


File: guile.info,  Node: Metaobjects and the Metaobject Protocol,  Next: Metaclasses,  Up: The Metaobject Protocol

8.11.1 Metaobjects and the Metaobject Protocol
----------------------------------------------

The building blocks of GOOPS are classes, slot definitions, instances,
generic functions and methods.  A class is a grouping of inheritance
relations and slot definitions.  An instance is an object with slots
that are allocated following the rules implied by its class’s
superclasses and slot definitions.  A generic function is a collection
of methods and rules for determining which of those methods to apply
when the generic function is invoked.  A method is a procedure and a set
of specializers that specify the type of arguments to which the
procedure is applicable.

   Of these entities, GOOPS represents classes, generic functions and
methods as “metaobjects”.  In other words, the values in a GOOPS program
that describe classes, generic functions and methods, are themselves
instances (or “objects”) of special GOOPS classes that encapsulate the
behaviour, respectively, of classes, generic functions, and methods.

   (The other two entities are slot definitions and instances.  Slot
definitions are not strictly instances, but every slot definition is
associated with a GOOPS class that specifies the behaviour of the slot
as regards accessibility and protection from garbage collection.
Instances are of course objects in the usual sense, and there is no
benefit from thinking of them as metaobjects.)

   The “metaobject protocol” (or “MOP”) is the specification of the
generic functions which determine the behaviour of these metaobjects and
the circumstances in which these generic functions are invoked.

   For a concrete example of what this means, consider how GOOPS
calculates the set of slots for a class that is being defined using
‘define-class’.  The desired set of slots is the union of the new
class’s direct slots and the slots of all its superclasses.  But
‘define-class’ itself does not perform this calculation.  Instead, there
is a method of the ‘initialize’ generic function that is specialized for
instances of type ‘<class>’, and it is this method that performs the
slot calculation.

   ‘initialize’ is a generic function which GOOPS calls whenever a new
instance is created, immediately after allocating memory for a new
instance, in order to initialize the new instance’s slots.  The sequence
of steps is as follows.

   • ‘define-class’ uses ‘make’ to make a new instance of the ‘<class>’
     class, passing as initialization arguments the superclasses, slot
     definitions and class options that were specified in the
     ‘define-class’ form.

   • ‘make’ allocates memory for the new instance, and invokes the
     ‘initialize’ generic function to initialize the new instance’s
     slots.

   • The ‘initialize’ generic function applies the method that is
     specialized for instances of type ‘<class>’, and this method
     performs the slot calculation.

   In other words, rather than being hardcoded in ‘define-class’, the
default behaviour of class definition is encapsulated by generic
function methods that are specialized for the class ‘<class>’.

   It is possible to create a new class that inherits from ‘<class>’,
which is called a “metaclass”, and to write a new ‘initialize’ method
that is specialized for instances of the new metaclass.  Then, if the
‘define-class’ form includes a ‘#:metaclass’ class option whose value is
the new metaclass, the class that is defined by the ‘define-class’ form
will be an instance of the new metaclass rather than of the default
‘<class>’, and will be defined in accordance with the new ‘initialize’
method.  Thus the default slot calculation, as well as any other aspect
of the new class’s relationship with its superclasses, can be modified
or overridden.

   In a similar way, the behaviour of generic functions can be modified
or overridden by creating a new class that inherits from the standard
generic function class ‘<generic>’, writing appropriate methods that are
specialized to the new class, and creating new generic functions that
are instances of the new class.

   The same is true for method metaobjects.  And the same basic
mechanism allows the application class author to write an ‘initialize’
method that is specialized to their application class, to initialize
instances of that class.

   Such is the power of the MOP. Note that ‘initialize’ is just one of a
large number of generic functions that can be customized to modify the
behaviour of application objects and classes and of GOOPS itself.  Each
following section covers a particular area of GOOPS functionality, and
describes the generic functions that are relevant for customization of
that area.


File: guile.info,  Node: Metaclasses,  Next: MOP Specification,  Prev: Metaobjects and the Metaobject Protocol,  Up: The Metaobject Protocol

8.11.2 Metaclasses
------------------

A "metaclass" is the class of an object which represents a GOOPS class.
Put more succinctly, a metaclass is a class’s class.

   Most GOOPS classes have the metaclass ‘<class>’ and, by default, any
new class that is created using ‘define-class’ has the metaclass
‘<class>’.

   But what does this really mean?  To find out, let’s look in more
detail at what happens when a new class is created using ‘define-class’:

     (define-class <my-class> (<object>) . slots)

Guile expands this to something like:

     (define <my-class> (class (<object>) . slots))

which in turn expands to:

     (define <my-class>
       (make <class> #:dsupers (list <object>) #:slots slots))

   As this expansion makes clear, the resulting value of ‘<my-class>’ is
an instance of the class ‘<class>’ with slot values specifying the
superclasses and slot definitions for the class ‘<my-class>’.
(‘#:dsupers’ and ‘#:slots’ are initialization keywords for the ‘dsupers’
and ‘dslots’ slots of the ‘<class>’ class.)

   Now suppose that you want to define a new class with a metaclass
other than the default ‘<class>’.  This is done by writing:

     (define-class <my-class2> (<object>)
        slot …
        #:metaclass <my-metaclass>)

and Guile expands _this_ to something like:

     (define <my-class2>
       (make <my-metaclass> #:dsupers (list <object>) #:slots slots))

   In this case, the value of ‘<my-class2>’ is an instance of the more
specialized class ‘<my-metaclass>’.  Note that ‘<my-metaclass>’ itself
must previously have been defined as a subclass of ‘<class>’.  For a
full discussion of when and how it is useful to define new metaclasses,
see *note MOP Specification::.

   Now let’s make an instance of ‘<my-class2>’:

     (define my-object (make <my-class2> ...))

   All of the following statements are correct expressions of the
relationships between ‘my-object’, ‘<my-class2>’, ‘<my-metaclass>’ and
‘<class>’.

   • ‘my-object’ is an instance of the class ‘<my-class2>’.

   • ‘<my-class2>’ is an instance of the class ‘<my-metaclass>’.

   • ‘<my-metaclass>’ is an instance of the class ‘<class>’.

   • The class of ‘my-object’ is ‘<my-class2>’.

   • The class of ‘<my-class2>’ is ‘<my-metaclass>’.

   • The class of ‘<my-metaclass>’ is ‘<class>’.


File: guile.info,  Node: MOP Specification,  Next: Instance Creation Protocol,  Prev: Metaclasses,  Up: The Metaobject Protocol

8.11.3 MOP Specification
------------------------

The aim of the MOP specification in this chapter is to specify all the
customizable generic function invocations that can be made by the
standard GOOPS syntax, procedures and methods, and to explain the
protocol for customizing such invocations.

   A generic function invocation is customizable if the types of the
arguments to which it is applied are not completely determined by the
lexical context in which the invocation appears.  For example, the
‘(initialize INSTANCE INITARGS)’ invocation in the default
‘make-instance’ method is customizable, because the type of the
‘INSTANCE’ argument is determined by the class that was passed to
‘make-instance’.

   (Whereas — to give a counter-example — the ‘(make <generic> #:name
',name)’ invocation in ‘define-generic’ is not customizable, because all
of its arguments have lexically determined types.)

   When using this rule to decide whether a given generic function
invocation is customizable, we ignore arguments that are expected to be
handled in method definitions as a single “rest” list argument.

   For each customizable generic function invocation, the "invocation
protocol" is explained by specifying

   • what, conceptually, the applied method is intended to do

   • what assumptions, if any, the caller makes about the applied
     method’s side effects

   • what the caller expects to get as the applied method’s return
     value.


File: guile.info,  Node: Instance Creation Protocol,  Next: Class Definition Protocol,  Prev: MOP Specification,  Up: The Metaobject Protocol

8.11.4 Instance Creation Protocol
---------------------------------

‘make <class> . INITARGS’ (method)

   • ‘allocate-instance CLASS INITARGS’ (generic)

     The applied ‘allocate-instance’ method should allocate storage for
     a new instance of class CLASS and return the uninitialized
     instance.

   • ‘initialize INSTANCE INITARGS’ (generic)

     INSTANCE is the uninitialized instance returned by
     ‘allocate-instance’.  The applied method should initialize the new
     instance in whatever sense is appropriate for its class.  The
     method’s return value is ignored.

   ‘make’ itself is a generic function.  Hence the ‘make’ invocation
itself can be customized in the case where the new instance’s metaclass
is more specialized than the default ‘<class>’, by defining a ‘make’
method that is specialized to that metaclass.

   Normally, however, the method for classes with metaclass ‘<class>’
will be applied.  This method calls two generic functions:

   • (allocate-instance CLASS .  INITARGS)

   • (initialize INSTANCE .  INITARGS)

   ‘allocate-instance’ allocates storage for and returns the new
instance, uninitialized.  You might customize ‘allocate-instance’, for
example, if you wanted to provide a GOOPS wrapper around some other
object programming system.

   To do this, you would create a specialized metaclass, which would act
as the metaclass for all classes and instances from the other system.
Then define an ‘allocate-instance’ method, specialized to that
metaclass, which calls a Guile primitive C function (or FFI code), which
in turn allocates the new instance using the interface of the other
object system.

   In this case, for a complete system, you would also need to customize
a number of other generic functions like ‘make’ and ‘initialize’, so
that GOOPS knows how to make classes from the other system, access
instance slots, and so on.

   ‘initialize’ initializes the instance that is returned by
‘allocate-instance’.  The standard GOOPS methods perform initializations
appropriate to the instance class.

   • At the least specialized level, the method for instances of type
     ‘<object>’ performs internal GOOPS instance initialization, and
     initializes the instance’s slots according to the slot definitions
     and any slot initialization keywords that appear in INITARGS.

   • The method for instances of type ‘<class>’ calls ‘(next-method)’,
     then performs the class initializations described in *note Class
     Definition Protocol::.

   • and so on for generic functions, methods, operator classes …

   Similarly, you can customize the initialization of instances of any
application-defined class by defining an ‘initialize’ method specialized
to that class.

   Imagine a class whose instances’ slots need to be initialized at
instance creation time by querying a database.  Although it might be
possible to achieve this a combination of ‘#:init-thunk’ keywords and
closures in the slot definitions, it may be neater to write an
‘initialize’ method for the class that queries the database once and
initializes all the dependent slot values according to the results.


File: guile.info,  Node: Class Definition Protocol,  Next: Customizing Class Definition,  Prev: Instance Creation Protocol,  Up: The Metaobject Protocol

8.11.5 Class Definition Protocol
--------------------------------

Here is a summary diagram of the syntax, procedures and generic
functions that may be involved in class definition.

‘define-class’ (syntax)

   • ‘class’ (syntax)

        • ‘make-class’ (procedure)

             • ‘ensure-metaclass’ (procedure)

             • ‘make METACLASS …’ (generic)

                  • ‘allocate-instance’ (generic)

                  • ‘initialize’ (generic)

                       • ‘compute-cpl’ (generic)

                            • ‘compute-std-cpl’ (procedure)

                       • ‘compute-slots’ (generic)

                       • ‘compute-get-n-set’ (generic)

                       • ‘compute-getter-method’ (generic)

                       • ‘compute-setter-method’ (generic)

   • ‘class-redefinition’ (generic)

        • ‘remove-class-accessors’ (generic)

        • ‘update-direct-method!’ (generic)

        • ‘update-direct-subclass!’ (generic)

   Wherever a step above is marked as “generic”, it can be customized,
and the detail shown below it is only “correct” insofar as it describes
what the default method of that generic function does.  For example, if
you write an ‘initialize’ method, for some metaclass, that does not call
‘next-method’ and does not call ‘compute-cpl’, then ‘compute-cpl’ will
not be called when a class is defined with that metaclass.

   A ‘(define-class ...)’ form (*note Class Definition::) expands to an
expression which

   • checks that it is being evaluated only at top level

   • defines any accessors that are implied by the SLOT-DEFINITIONs

   • uses ‘class’ to create the new class

   • checks for a previous class definition for NAME and, if found,
     handles the redefinition by invoking ‘class-redefinition’ (*note
     Redefining a Class::).

 -- syntax: class name (super …) slot-definition … class-option …
     Return a newly created class that inherits from SUPERs, with direct
     slots defined by SLOT-DEFINITIONs and CLASS-OPTIONs.  For the
     format of SLOT-DEFINITIONs and CLASS-OPTIONs, see *note
     define-class: Class Definition.

‘class’ expands to an expression which

   • processes the class and slot definition options to check that they
     are well-formed, to convert the ‘#:init-form’ option to an
     ‘#:init-thunk’ option, to supply a default environment parameter
     (the current top-level environment) and to evaluate all the bits
     that need to be evaluated

   • calls ‘make-class’ to create the class with the processed and
     evaluated parameters.

 -- procedure: make-class supers slots class-option …
     Return a newly created class that inherits from SUPERS, with direct
     slots defined by SLOTS and CLASS-OPTIONs.  For the format of SLOTS
     and CLASS-OPTIONs, see *note define-class: Class Definition, except
     note that for ‘make-class’, SLOTS is a separate list of slot
     definitions.

‘make-class’

   • adds ‘<object>’ to the SUPERS list if SUPERS is empty or if none of
     the classes in SUPERS have ‘<object>’ in their class precedence
     list

   • defaults the ‘#:environment’, ‘#:name’ and ‘#:metaclass’ options,
     if they are not specified by OPTIONS, to the current top-level
     environment, the unbound value, and ‘(ensure-metaclass SUPERS)’
     respectively

   • checks for duplicate classes in SUPERS and duplicate slot names in
     SLOTS, and signals an error if there are any duplicates

   • calls ‘make’, passing the metaclass as the first parameter and all
     other parameters as option keywords with values.

 -- procedure: ensure-metaclass supers env
     Return a metaclass suitable for a class that inherits from the list
     of classes in SUPERS.  The returned metaclass is the union by
     inheritance of the metaclasses of the classes in SUPERS.

     In the simplest case, where all the SUPERS are straightforward
     classes with metaclass ‘<class>’, the returned metaclass is just
     ‘<class>’.

     For a more complex example, suppose that SUPERS contained one class
     with metaclass ‘<operator-class>’ and one with metaclass
     ‘<foreign-object-class>’.  Then the returned metaclass would be a
     class that inherits from both ‘<operator-class>’ and
     ‘<foreign-object-class>’.

     If SUPERS is the empty list, ‘ensure-metaclass’ returns the default
     GOOPS metaclass ‘<class>’.

     GOOPS keeps a list of the metaclasses created by
     ‘ensure-metaclass’, so that each required type of metaclass only
     has to be created once.

     The ‘env’ parameter is ignored.

 -- generic: make metaclass initarg …
     METACLASS is the metaclass of the class being defined, either taken
     from the ‘#:metaclass’ class option or computed by
     ‘ensure-metaclass’.  The applied method must create and return the
     fully initialized class metaobject for the new class definition.

   The ‘(make METACLASS INITARG …)’ invocation is a particular case of
the instance creation protocol covered in the previous section.  It will
create an class metaobject with metaclass METACLASS.  By default, this
metaobject will be initialized by the ‘initialize’ method that is
specialized for instances of type ‘<class>’.

   The ‘initialize’ method for classes (signature ‘(initialize <class>
initargs)’) calls the following generic functions.

   • ‘compute-cpl CLASS’ (generic)

     The applied method should compute and return the class precedence
     list for CLASS as a list of class metaobjects.  When ‘compute-cpl’
     is called, the following CLASS metaobject slots have all been
     initialized: ‘name’, ‘direct-supers’, ‘direct-slots’,
     ‘direct-subclasses’ (empty), ‘direct-methods’.  The value returned
     by ‘compute-cpl’ will be stored in the ‘cpl’ slot.

   • ‘compute-slots CLASS’ (generic)

     The applied method should compute and return the slots (union of
     direct and inherited) for CLASS as a list of slot definitions.
     When ‘compute-slots’ is called, all the CLASS metaobject slots
     mentioned for ‘compute-cpl’ have been initialized, plus the
     following: ‘cpl’, ‘redefined’ (‘#f’), ‘environment’.  The value
     returned by ‘compute-slots’ will be stored in the ‘slots’ slot.

   • ‘compute-get-n-set CLASS SLOT-DEF’ (generic)

     ‘initialize’ calls ‘compute-get-n-set’ for each slot computed by
     ‘compute-slots’.  The applied method should compute and return a
     pair of closures that, respectively, get and set the value of the
     specified slot.  The get closure should have arity 1 and expect a
     single argument that is the instance whose slot value is to be
     retrieved.  The set closure should have arity 2 and expect two
     arguments, where the first argument is the instance whose slot
     value is to be set and the second argument is the new value for
     that slot.  The closures should be returned in a two element list:
     ‘(list GET SET)’.

     The closures returned by ‘compute-get-n-set’ are stored as part of
     the value of the CLASS metaobject’s ‘getters-n-setters’ slot.
     Specifically, the value of this slot is a list with the same number
     of elements as there are slots in the class, and each element looks
     either like

          (SLOT-NAME-SYMBOL INIT-FUNCTION . INDEX)

     or like

          (SLOT-NAME-SYMBOL INIT-FUNCTION GET SET)

     Where the get and set closures are replaced by INDEX, the slot is
     an instance slot and INDEX is the slot’s index in the underlying
     structure: GOOPS knows how to get and set the value of such slots
     and so does not need specially constructed get and set closures.
     Otherwise, GET and SET are the closures returned by
     ‘compute-get-n-set’.

     The structure of the ‘getters-n-setters’ slot value is important
     when understanding the next customizable generic functions that
     ‘initialize’ calls…

   • ‘compute-getter-method CLASS GNS’ (generic)

     ‘initialize’ calls ‘compute-getter-method’ for each of the class’s
     slots (as determined by ‘compute-slots’) that includes a ‘#:getter’
     or ‘#:accessor’ slot option.  GNS is the element of the CLASS
     metaobject’s ‘getters-n-setters’ slot that specifies how the slot
     in question is referenced and set, as described above under
     ‘compute-get-n-set’.  The applied method should create and return a
     method that is specialized for instances of type CLASS and uses the
     get closure to retrieve the slot’s value.  ‘initialize’ uses
     ‘add-method!’ to add the returned method to the generic function
     named by the slot definition’s ‘#:getter’ or ‘#:accessor’ option.

   • ‘compute-setter-method CLASS GNS’ (generic)

     ‘compute-setter-method’ is invoked with the same arguments as
     ‘compute-getter-method’, for each of the class’s slots that
     includes a ‘#:setter’ or ‘#:accessor’ slot option.  The applied
     method should create and return a method that is specialized for
     instances of type CLASS and uses the set closure to set the slot’s
     value.  ‘initialize’ then uses ‘add-method!’ to add the returned
     method to the generic function named by the slot definition’s
     ‘#:setter’ or ‘#:accessor’ option.


File: guile.info,  Node: Customizing Class Definition,  Next: Method Definition,  Prev: Class Definition Protocol,  Up: The Metaobject Protocol

8.11.6 Customizing Class Definition
-----------------------------------

If the metaclass of the new class is something more specialized than the
default ‘<class>’, then the type of CLASS in the calls above is more
specialized than ‘<class>’, and hence it becomes possible to define
generic function methods, specialized for the new class’s metaclass,
that can modify or override the default behaviour of ‘initialize’,
‘compute-cpl’ or ‘compute-get-n-set’.

   ‘compute-cpl’ computes the class precedence list (“CPL”) for the new
class (*note Class Precedence List::), and returns it as a list of class
objects.  The CPL is important because it defines a superclass ordering
that is used, when a generic function is invoked upon an instance of the
class, to decide which of the available generic function methods is the
most specific.  Hence ‘compute-cpl’ could be customized in order to
modify the CPL ordering algorithm for all classes with a special
metaclass.

   The default CPL algorithm is encapsulated by the ‘compute-std-cpl’
procedure, which is called by the default ‘compute-cpl’ method.

 -- procedure: compute-std-cpl class
     Compute and return the class precedence list for CLASS according to
     the algorithm described in *note Class Precedence List::.

   ‘compute-slots’ computes and returns a list of all slot definitions
for the new class.  By default, this list includes the direct slot
definitions from the ‘define-class’ form, plus the slot definitions that
are inherited from the new class’s superclasses.  The default
‘compute-slots’ method uses the CPL computed by ‘compute-cpl’ to
calculate this union of slot definitions, with the rule that slots
inherited from superclasses are shadowed by direct slots with the same
name.  One possible reason for customizing ‘compute-slots’ would be to
implement an alternative resolution strategy for slot name conflicts.

   ‘compute-get-n-set’ computes the low-level closures that will be used
to get and set the value of a particular slot, and returns them in a
list with two elements.

   The closures returned depend on how storage for that slot is
allocated.  The standard ‘compute-get-n-set’ method, specialized for
classes of type ‘<class>’, handles the standard GOOPS values for the
‘#:allocation’ slot option (*note allocation: Slot Options.).  By
defining a new ‘compute-get-n-set’ method for a more specialized
metaclass, it is possible to support new types of slot allocation.

   Suppose you wanted to create a large number of instances of some
class with a slot that should be shared between some but not all
instances of that class - say every 10 instances should share the same
slot storage.  The following example shows how to implement and use a
new type of slot allocation to do this.

     (define-class <batched-allocation-metaclass> (<class>))

     (let ((batch-allocation-count 0)
           (batch-get-n-set #f))
       (define-method (compute-get-n-set
                          (class <batched-allocation-metaclass>) s)
         (case (slot-definition-allocation s)
           ((#:batched)
            ;; If we've already used the same slot storage for 10 instances,
            ;; reset variables.
            (if (= batch-allocation-count 10)
                (begin
                  (set! batch-allocation-count 0)
                  (set! batch-get-n-set #f)))
            ;; If we don't have a current pair of get and set closures,
            ;; create one.  make-closure-variable returns a pair of closures
            ;; around a single Scheme variable - see goops.scm for details.
            (or batch-get-n-set
                (set! batch-get-n-set (make-closure-variable)))
            ;; Increment the batch allocation count.
            (set! batch-allocation-count (+ batch-allocation-count 1))
            batch-get-n-set)

           ;; Call next-method to handle standard allocation types.
           (else (next-method)))))

     (define-class <class-using-batched-slot> ()
       ...
       (c #:allocation #:batched)
       ...
       #:metaclass <batched-allocation-metaclass>)

   The usage of ‘compute-getter-method’ and ‘compute-setter-method’ is
described in *note Class Definition Protocol::.

   ‘compute-cpl’ and ‘compute-get-n-set’ are called by the standard
‘initialize’ method for classes whose metaclass is ‘<class>’.  But
‘initialize’ itself can also be modified, by defining an ‘initialize’
method specialized to the new class’s metaclass.  Such a method could
complete override the standard behaviour, by not calling ‘(next-method)’
at all, but more typically it would perform additional class
initialization steps before and/or after calling ‘(next-method)’ for the
standard behaviour.


File: guile.info,  Node: Method Definition,  Next: Method Definition Internals,  Prev: Customizing Class Definition,  Up: The Metaobject Protocol

8.11.7 Method Definition
------------------------

‘define-method’ (syntax)

   • ‘add-method! TARGET METHOD’ (generic)

‘define-method’ invokes the ‘add-method!’ generic function to handle
adding the new method to a variety of possible targets.  GOOPS includes
methods to handle TARGET as

   • a generic function (the most common case)

   • a procedure

   • a primitive generic (*note Extending Primitives::)

   By defining further methods for ‘add-method!’, you can theoretically
handle adding methods to further types of target.


File: guile.info,  Node: Method Definition Internals,  Next: Generic Function Internals,  Prev: Method Definition,  Up: The Metaobject Protocol

8.11.8 Method Definition Internals
----------------------------------

‘define-method’:

   • checks the form of the first parameter, and applies the following
     steps to the accessor’s setter if it has the ‘(setter …)’ form

   • interpolates a call to ‘define-generic’ or ‘define-accessor’ if a
     generic function is not already defined with the supplied name

   • calls ‘method’ with the PARAMETERs and BODY, to make a new method
     instance

   • calls ‘add-method!’ to add this method to the relevant generic
     function.

 -- syntax: method (parameter …) body …
     Make a method whose specializers are defined by the classes in
     PARAMETERs and whose procedure definition is constructed from the
     PARAMETER symbols and BODY forms.

     The PARAMETER and BODY parameters should be as for ‘define-method’
     (*note define-method: Methods and Generic Functions.).

‘method’:

   • extracts formals and specializing classes from the PARAMETERs,
     defaulting the class for unspecialized parameters to ‘<top>’

   • creates a closure using the formals and the BODY forms

   • calls ‘make’ with metaclass ‘<method>’ and the specializers and
     closure using the ‘#:specializers’ and ‘#:procedure’ keywords.

 -- procedure: make-method specializers procedure
     Make a method using SPECIALIZERS and PROCEDURE.

     SPECIALIZERS should be a list of classes that specifies the
     parameter combinations to which this method will be applicable.

     PROCEDURE should be the closure that will applied to the generic
     function parameters when this method is invoked.

‘make-method’ is a simple wrapper around ‘make’ with metaclass
‘<method>’.

 -- generic: add-method! target method
     Generic function for adding method METHOD to TARGET.

 -- method: add-method! (generic <generic>) (method <method>)
     Add method METHOD to the generic function GENERIC.

 -- method: add-method! (proc <procedure>) (method <method>)
     If PROC is a procedure with generic capability (*note
     generic-capability?: Extending Primitives.), upgrade it to a
     primitive generic and add METHOD to its generic function
     definition.

 -- method: add-method! (pg <primitive-generic>) (method <method>)
     Add method METHOD to the generic function definition of PG.

     Implementation: ‘(add-method! (primitive-generic-generic pg)
     method)’.

 -- method: add-method! (whatever <top>) (method <method>)
     Raise an error indicating that WHATEVER is not a valid generic
     function.


File: guile.info,  Node: Generic Function Internals,  Next: Generic Function Invocation,  Prev: Method Definition Internals,  Up: The Metaobject Protocol

8.11.9 Generic Function Internals
---------------------------------

‘define-generic’ calls ‘ensure-generic’ to upgrade a pre-existing
procedure value, or ‘make’ with metaclass ‘<generic>’ to create a new
generic function.

   ‘define-accessor’ calls ‘ensure-accessor’ to upgrade a pre-existing
procedure value, or ‘make-accessor’ to create a new accessor.

 -- procedure: ensure-generic old-definition [name]
     Return a generic function with name NAME, if possible by using or
     upgrading OLD-DEFINITION.  If unspecified, NAME defaults to ‘#f’.

     If OLD-DEFINITION is already a generic function, it is returned
     unchanged.

     If OLD-DEFINITION is a Scheme procedure or procedure-with-setter,
     ‘ensure-generic’ returns a new generic function that uses
     OLD-DEFINITION for its default procedure and setter.

     Otherwise ‘ensure-generic’ returns a new generic function with no
     defaults and no methods.

 -- procedure: make-generic [name]
     Return a new generic function with name ‘(car NAME)’.  If
     unspecified, NAME defaults to ‘#f’.

   ‘ensure-generic’ calls ‘make’ with metaclasses ‘<generic>’ and
‘<generic-with-setter>’, depending on the previous value of the variable
that it is trying to upgrade.

   ‘make-generic’ is a simple wrapper for ‘make’ with metaclass
‘<generic>’.

 -- procedure: ensure-accessor proc [name]
     Return an accessor with name NAME, if possible by using or
     upgrading PROC.  If unspecified, NAME defaults to ‘#f’.

     If PROC is already an accessor, it is returned unchanged.

     If PROC is a Scheme procedure, procedure-with-setter or generic
     function, ‘ensure-accessor’ returns an accessor that reuses the
     reusable elements of PROC.

     Otherwise ‘ensure-accessor’ returns a new accessor with no defaults
     and no methods.

 -- procedure: make-accessor [name]
     Return a new accessor with name ‘(car NAME)’.  If unspecified, NAME
     defaults to ‘#f’.

   ‘ensure-accessor’ calls ‘make’ with metaclass
‘<generic-with-setter>’, as well as calls to ‘ensure-generic’,
‘make-accessor’ and (tail recursively) ‘ensure-accessor’.

   ‘make-accessor’ calls ‘make’ twice, first with metaclass ‘<generic>’
to create a generic function for the setter, then with metaclass
‘<generic-with-setter>’ to create the accessor, passing the setter
generic function as the value of the ‘#:setter’ keyword.


File: guile.info,  Node: Generic Function Invocation,  Prev: Generic Function Internals,  Up: The Metaobject Protocol

8.11.10 Generic Function Invocation
-----------------------------------

There is a detailed and customizable protocol involved in the process of
invoking a generic function — i.e., in the process of deciding which of
the generic function’s methods are applicable to the current arguments,
and which one of those to apply.  Here is a summary diagram of the
generic functions involved.

‘apply-generic’ (generic)

   • ‘no-method’ (generic)

   • ‘compute-applicable-methods’ (generic)

   • ‘sort-applicable-methods’ (generic)

        • ‘method-more-specific?’ (generic)

   • ‘apply-methods’ (generic)

        • ‘apply-method’ (generic)

        • ‘no-next-method’ (generic)

   • ‘no-applicable-method’

   We do not yet have full documentation for these.  Please refer to the
code (‘oop/goops.scm’) for details.


File: guile.info,  Node: Redefining a Class,  Next: Changing the Class of an Instance,  Prev: The Metaobject Protocol,  Up: GOOPS

8.12 Redefining a Class
=======================

Suppose that a class ‘<my-class>’ is defined using ‘define-class’ (*note
define-class: Class Definition.), with slots that have accessor
functions, and that an application has created several instances of
‘<my-class>’ using ‘make’ (*note make: Instance Creation.).  What then
happens if ‘<my-class>’ is redefined by calling ‘define-class’ again?

* Menu:

* Default Class Redefinition Behaviour::
* Customizing Class Redefinition::


File: guile.info,  Node: Default Class Redefinition Behaviour,  Next: Customizing Class Redefinition,  Up: Redefining a Class

8.12.1 Default Class Redefinition Behaviour
-------------------------------------------

GOOPS’ default answer to this question is as follows.

   • All existing direct instances of ‘<my-class>’ are converted to be
     instances of the new class.  This is achieved by preserving the
     values of slots that exist in both the old and new definitions, and
     initializing the values of new slots in the usual way (*note make:
     Instance Creation.).

   • All existing subclasses of ‘<my-class>’ are redefined, as though
     the ‘define-class’ expressions that defined them were re-evaluated
     following the redefinition of ‘<my-class>’, and the class
     redefinition process described here is applied recursively to the
     redefined subclasses.

   • Once all of its instances and subclasses have been updated, the
     class metaobject previously bound to the variable ‘<my-class>’ is
     no longer needed and so can be allowed to be garbage collected.

   To keep things tidy, GOOPS also needs to do a little housekeeping on
methods that are associated with the redefined class.

   • Slot accessor methods for slots in the old definition should be
     removed from their generic functions.  They will be replaced by
     accessor methods for the slots of the new class definition.

   • Any generic function method that uses the old ‘<my-class>’
     metaobject as one of its formal parameter specializers must be
     updated to refer to the new ‘<my-class>’ metaobject.  (Whenever a
     new generic function method is defined, ‘define-method’ adds the
     method to a list stored in the class metaobject for each class used
     as a formal parameter specializer, so it is easy to identify all
     the methods that must be updated when a class is redefined.)

   If this class redefinition strategy strikes you as rather
counter-intuitive, bear in mind that it is derived from similar
behaviour in other object systems such as CLOS, and that experience in
those systems has shown it to be very useful in practice.

   Also bear in mind that, like most of GOOPS’ default behaviour, it can
be customized…


File: guile.info,  Node: Customizing Class Redefinition,  Prev: Default Class Redefinition Behaviour,  Up: Redefining a Class

8.12.2 Customizing Class Redefinition
-------------------------------------

When ‘define-class’ notices that a class is being redefined, it
constructs the new class metaobject as usual, then invokes the
‘class-redefinition’ generic function with the old and new classes as
arguments.  Therefore, if the old or new classes have metaclasses other
than the default ‘<class>’, class redefinition behaviour can be
customized by defining a ‘class-redefinition’ method that is specialized
for the relevant metaclasses.

 -- generic: class-redefinition
     Handle the class redefinition from OLD-CLASS to NEW-CLASS, and
     return the new class metaobject that should be bound to the
     variable specified by ‘define-class’’s first argument.

 -- method: class-redefinition (old-class <class>) (new-class <class>)
     Implements GOOPS’ default class redefinition behaviour, as
     described in *note Default Class Redefinition Behaviour::.  Returns
     the metaobject for the new class definition.

   The default ‘class-redefinition’ method, for classes with the default
metaclass ‘<class>’, calls the following generic functions, which could
of course be individually customized.

 -- generic: remove-class-accessors! old
     The default ‘remove-class-accessors!’ method removes the accessor
     methods of the old class from all classes which they specialize.

 -- generic: update-direct-method! method old new
     The default ‘update-direct-method!’ method substitutes the new
     class for the old in all methods specialized to the old class.

 -- generic: update-direct-subclass! subclass old new
     The default ‘update-direct-subclass!’ method invokes
     ‘class-redefinition’ recursively to handle the redefinition of
     subclasses.

   An alternative class redefinition strategy could be to leave all
existing instances as instances of the old class, but accepting that the
old class is now “nameless”, since its name has been taken over by the
new definition.  In this strategy, any existing subclasses could also be
left as they are, on the understanding that they inherit from a nameless
superclass.

   This strategy is easily implemented in GOOPS, by defining a new
metaclass, that will be used as the metaclass for all classes to which
the strategy should apply, and then defining a ‘class-redefinition’
method that is specialized for this metaclass:

     (define-class <can-be-nameless> (<class>))

     (define-method (class-redefinition (old <can-be-nameless>)
                                        (new <class>))
       new)

   When customization can be as easy as this, aren’t you glad that GOOPS
implements the far more difficult strategy as its default!


File: guile.info,  Node: Changing the Class of an Instance,  Prev: Redefining a Class,  Up: GOOPS

8.13 Changing the Class of an Instance
======================================

When a class is redefined, any existing instance of the redefined class
will be modified for the new class definition before the next time that
any of the instance’s slots is referenced or set.  GOOPS modifies each
instance by calling the generic function ‘change-class’.

   More generally, you can change the class of an existing instance at
any time by invoking the generic function ‘change-class’ with two
arguments: the instance and the new class.

   The default method for ‘change-class’ decides how to implement the
change of class by looking at the slot definitions for the instance’s
existing class and for the new class.  If the new class has slots with
the same name as slots in the existing class, the values for those slots
are preserved.  Slots that are present only in the existing class are
discarded.  Slots that are present only in the new class are initialized
using the corresponding slot definition’s init function (*note
slot-init-function: Classes.).

 -- generic: change-class instance new-class

 -- method: change-class (obj <object>) (new <class>)
     Modify instance OBJ to make it an instance of class NEW.

     The value of each of OBJ’s slots is preserved only if a similarly
     named slot exists in NEW; any other slot values are discarded.

     The slots in NEW that do not correspond to any of OBJ’s
     pre-existing slots are initialized according to NEW’s slot
     definitions’ init functions.

   The default ‘change-class’ method also invokes another generic
function, ‘update-instance-for-different-class’, as the last thing that
it does before returning.  The applied
‘update-instance-for-different-class’ method can make any further
adjustments to NEW-INSTANCE that are required to complete or modify the
change of class.  The return value from the applied method is ignored.

 -- generic: update-instance-for-different-class old-instance
          new-instance
     A generic function that can be customized to put finishing touches
     to an instance whose class has just been changed.  The default
     ‘update-instance-for-different-class’ method does nothing.

   Customized change of class behaviour can be implemented by defining
‘change-class’ methods that are specialized either by the class of the
instances to be modified or by the metaclass of the new class.


File: guile.info,  Node: Guile Implementation,  Next: GNU Free Documentation License,  Prev: GOOPS,  Up: Top

9 Guile Implementation
**********************

At some point, after one has been programming in Scheme for some time,
another level of Scheme comes into view: its implementation.  Knowledge
of how Scheme can be implemented turns out to be necessary to become an
expert hacker.  As Peter Norvig notes in his retrospective on PAIP(1),
“The expert Lisp programmer eventually develops a good ‘efficiency
model’.”

   By this Norvig means that over time, the Lisp hacker eventually
develops an understanding of how much her code “costs” in terms of space
and time.

   This chapter describes Guile as an implementation of Scheme: its
history, how it represents and evaluates its data, and its compiler.
This knowledge can help you to make that step from being one who is
merely familiar with Scheme to being a real hacker.

* Menu:

* History::                          A brief history of Guile.
* Data Representation::              How Guile represents Scheme data.
* A Virtual Machine for Guile::      How compiled procedures work.
* Compiling to the Virtual Machine:: Not as hard as you might think.

   ---------- Footnotes ----------

   (1) PAIP is the common abbreviation for ‘Paradigms of Artificial
Intelligence Programming’, an old but still useful text on Lisp.
Norvig’s retrospective sums up the lessons of PAIP, and can be found at
<http://norvig.com/Lisp-retro.html>.


File: guile.info,  Node: History,  Next: Data Representation,  Up: Guile Implementation

9.1 A Brief History of Guile
============================

Guile is an artifact of historical processes, both as code and as a
community of hackers.  It is sometimes useful to know this history when
hacking the source code, to know about past decisions and future
directions.

   Of course, the real history of Guile is written by the hackers
hacking and not the writers writing, so we round up the section with a
note on current status and future directions.

* Menu:

* The Emacs Thesis::  
* Early Days::                  
* A Scheme of Many Maintainers::  
* A Timeline of Selected Guile Releases::  
* Status::


File: guile.info,  Node: The Emacs Thesis,  Next: Early Days,  Up: History

9.1.1 The Emacs Thesis
----------------------

The story of Guile is the story of bringing the development experience
of Emacs to the mass of programs on a GNU system.

   Emacs, when it was first created in its GNU form in 1984, was a new
take on the problem of “how to make a program”.  The Emacs thesis is
that it is delightful to create composite programs based on an
orthogonal kernel written in a low-level language together with a
powerful, high-level extension language.

   Extension languages foster extensible programs, programs which adapt
readily to different users and to changing times.  Proof of this can be
seen in Emacs’ current and continued existence, spanning more than a
quarter-century.

   Besides providing for modification of a program by others, extension
languages are good for _intension_ as well.  Programs built in “the
Emacs way” are pleasurable and easy for their authors to flesh out with
the features that they need.

   After the Emacs experience was appreciated more widely, a number of
hackers started to consider how to spread this experience to the rest of
the GNU system.  It was clear that the easiest way to Emacsify a program
would be to embed a shared language implementation into it.


File: guile.info,  Node: Early Days,  Next: A Scheme of Many Maintainers,  Prev: The Emacs Thesis,  Up: History

9.1.2 Early Days
----------------

Tom Lord was the first to fully concentrate his efforts on an embeddable
language runtime, which he named “GEL”, the GNU Extension Language.

   GEL was the product of converting SCM, Aubrey Jaffer’s implementation
of Scheme, into something more appropriate to embedding as a library.
(SCM was itself based on an implementation by George Carrette, SIOD.)

   Lord managed to convince Richard Stallman to dub GEL the official
extension language for the GNU project.  It was a natural fit, given
that Scheme was a cleaner, more modern Lisp than Emacs Lisp.  Part of
the argument was that eventually when GEL became more capable, it could
gain the ability to execute other languages, especially Emacs Lisp.

   Due to a naming conflict with another programming language, Jim
Blandy suggested a new name for GEL: “Guile”.  Besides being a recursive
acronym, “Guile” craftily follows the naming of its ancestors,
“Planner”, “Conniver”, and “Schemer”.  (The latter was truncated to
“Scheme” due to a 6-character file name limit on an old operating
system.)  Finally, “Guile” suggests “guy-ell”, or “Guy L. Steele”, who,
together with Gerald Sussman, originally discovered Scheme.

   Around the same time that Guile (then GEL) was readying itself for
public release, another extension language was gaining in popularity,
Tcl.  Many developers found advantages in Tcl because of its shell-like
syntax and its well-developed graphical widgets library, Tk.  Also, at
the time there was a large marketing push promoting Tcl as a “universal
extension language”.

   Richard Stallman, as the primary author of GNU Emacs, had a
particular vision of what extension languages should be, and Tcl did not
seem to him to be as capable as Emacs Lisp.  He posted a criticism to
the comp.lang.tcl newsgroup, sparking one of the internet’s legendary
flamewars.  As part of these discussions, retrospectively dubbed the
“Tcl Wars”, he announced the Free Software Foundation’s intent to
promote Guile as the extension language for the GNU project.

   It is a common misconception that Guile was created as a reaction to
Tcl.  While it is true that the public announcement of Guile happened at
the same time as the “Tcl wars”, Guile was created out of a condition
that existed outside the polemic.  Indeed, the need for a powerful
language to bridge the gap between extension of existing applications
and a more fully dynamic programming environment is still with us today.


File: guile.info,  Node: A Scheme of Many Maintainers,  Next: A Timeline of Selected Guile Releases,  Prev: Early Days,  Up: History

9.1.3 A Scheme of Many Maintainers
----------------------------------

Surveying the field, it seems that Scheme implementations correspond
with their maintainers on an N-to-1 relationship.  That is to say, that
those people that implement Schemes might do so on a number of
occasions, but that the lifetime of a given Scheme is tied to the
maintainership of one individual.

   Guile is atypical in this regard.

   Tom Lord maintained Guile for its first year and a half or so,
corresponding to the end of 1994 through the middle of 1996.  The
releases made in this time constitute an arc from SCM as a standalone
program to Guile as a reusable, embeddable library, but passing through
a explosion of features: embedded Tcl and Tk, a toolchain for compiling
and disassembling Java, addition of a C-like syntax, creation of a
module system, and a start at a rich POSIX interface.

   Only some of those features remain in Guile.  There were ongoing
tensions between providing a small, embeddable language, and one which
had all of the features (e.g. a graphical toolkit) that a modern Emacs
might need.  In the end, as Guile gained in uptake, the development team
decided to focus on depth, documentation and orthogonality rather than
on breadth.  This has been the focus of Guile ever since, although there
is a wide range of third-party libraries for Guile.

   Jim Blandy presided over that period of stabilization, in the three
years until the end of 1999, when he too moved on to other projects.
Since then, Guile has had a group maintainership.  The first group was
Maciej Stachowiak, Mikael Djurfeldt, and Marius Vollmer, with Vollmer
staying on the longest.  By late 2007, Vollmer had mostly moved on to
other things, so Neil Jerram and Ludovic Courtès stepped up to take on
the primary maintenance responsibility.  Jerram and Courtès were joined
by Andy Wingo in late 2009.

   Of course, a large part of the actual work on Guile has come from
other contributors too numerous to mention, but without whom the world
would be a poorer place.


File: guile.info,  Node: A Timeline of Selected Guile Releases,  Next: Status,  Prev: A Scheme of Many Maintainers,  Up: History

9.1.4 A Timeline of Selected Guile Releases
-------------------------------------------

guile-i — 4 February 1995
     SCM, turned into a library.

guile-ii — 6 April 1995
     A low-level module system was added.  Tcl/Tk support was added,
     allowing extension of Scheme by Tcl or vice versa.  POSIX support
     was improved, and there was an experimental stab at Java
     integration.

guile-iii — 18 August 1995
     The C-like syntax, ctax, was improved, but mostly this release
     featured a start at the task of breaking Guile into pieces.

1.0 — 5 January 1997
     ‘#f’ was distinguished from ‘'()’.  User-level, cooperative
     multi-threading was added.  Source-level debugging became more
     useful, and programmer’s and user’s manuals were begun.  The module
     system gained a high-level interface, which is still used today in
     more or less the same form.

1.1 — 16 May 1997
1.2 — 24 June 1997
     Support for Tcl/Tk and ctax were split off as separate packages,
     and have remained there since.  Guile became more compatible with
     SCSH, and more useful as a UNIX scripting language.  Libguile could
     now be built as a shared library, and third-party extensions
     written in C became loadable via dynamic linking.

1.3.0 — 19 October 1998
     Command-line editing became much more pleasant through the use of
     the readline library.  The initial support for internationalization
     via multi-byte strings was removed; 10 years were to pass before
     proper internationalization would land again.  Initial Emacs Lisp
     support landed, ports gained better support for file descriptors,
     and fluids were added.

1.3.2 — 20 August 1999
1.3.4 — 25 September 1999
1.4 — 21 June 2000
     A long list of lispy features were added: hooks, Common Lisp’s
     ‘format’, optional and keyword procedure arguments, ‘getopt-long’,
     sorting, random numbers, and many other fixes and enhancements.
     Guile also gained an interactive debugger, interactive help, and
     better backtraces.

1.6 — 6 September 2002
     Guile gained support for the R5RS standard, and added a number of
     SRFI modules.  The module system was expanded with programmatic
     support for identifier selection and renaming.  The GOOPS object
     system was merged into Guile core.

1.8 — 20 February 2006
     Guile’s arbitrary-precision arithmetic switched to use the GMP
     library, and added support for exact rationals.  Guile’s embedded
     user-space threading was removed in favor of POSIX pre-emptive
     threads, providing true multiprocessing.  Gettext support was
     added, and Guile’s C API was cleaned up and orthogonalized in a
     massive way.

2.0 — 16 February 2010
     A virtual machine was added to Guile, along with the associated
     compiler and toolchain.  Support for internationalization was
     finally reimplemented, in terms of unicode, locales, and
     libunistring.  Running Guile instances became controllable and
     debuggable from within Emacs, via Geiser.  Guile caught up to
     features found in a number of other Schemes: SRFI-18 threads,
     module-hygienic macros, a profiler, tracer, and debugger, SSAX XML
     integration, bytevectors, a dynamic FFI, delimited continuations,
     module versions, and partial support for R6RS.


File: guile.info,  Node: Status,  Prev: A Timeline of Selected Guile Releases,  Up: History

9.1.5 Status, or: Your Help Needed
----------------------------------

Guile has achieved much of what it set out to achieve, but there is much
remaining to do.

   There is still the old problem of bringing existing applications into
a more Emacs-like experience.  Guile has had some successes in this
respect, but still most applications in the GNU system are without Guile
integration.

   Getting Guile to those applications takes an investment, the
“hacktivation energy” needed to wire Guile into a program that only pays
off once it is good enough to enable new kinds of behavior.  This would
be a great way for new hackers to contribute: take an application that
you use and that you know well, think of something that it can’t yet do,
and figure out a way to integrate Guile and implement that task in
Guile.

   With time, perhaps this exposure can reverse itself, whereby programs
can run under Guile instead of vice versa, eventually resulting in the
Emacsification of the entire GNU system.  Indeed, this is the reason for
the naming of the many Guile modules that live in the ‘ice-9’ namespace,
a nod to the fictional substance in Kurt Vonnegut’s novel, Cat’s Cradle,
capable of acting as a seed crystal to crystallize the mass of software.

   Implicit to this whole discussion is the idea that dynamic languages
are somehow better than languages like C. While languages like C have
their place, Guile’s take on this question is that yes, Scheme is more
expressive than C, and more fun to write.  This realization carries an
imperative with it to write as much code in Scheme as possible rather
than in other languages.

   These days it is possible to write extensible applications almost
entirely from high-level languages, through byte-code and native
compilation, speed gains in the underlying hardware, and foreign call
interfaces in the high-level language.  Smalltalk systems are like this,
as are Common Lisp-based systems.  While there already are a number of
pure-Guile applications out there, users still need to drop down to C
for some tasks: interfacing to system libraries that don’t have prebuilt
Guile interfaces, and for some tasks requiring high performance.

   The addition of the virtual machine in Guile 2.0, together with the
compiler infrastructure, should go a long way to addressing the speed
issues.  But there is much optimization to be done.  Interested
contributors will find lots of delightful low-hanging fruit, from simple
profile-driven optimization to hacking a just-in-time compiler from VM
bytecode to native code.

   Still, even with an all-Guile application, sometimes you want to
provide an opportunity for users to extend your program from a language
with a syntax that is closer to C, or to Python.  Another interesting
idea to consider is compiling e.g. Python to Guile.  It’s not that
far-fetched of an idea: see for example IronPython or JRuby.

   And then there’s Emacs itself.  Though there is a somewhat-working
Emacs Lisp language frontend for Guile, it cannot yet execute all of
Emacs Lisp.  A serious integration of Guile with Emacs would replace the
Elisp virtual machine with Guile, and provide the necessary C shims so
that Guile could emulate Emacs’ C API. This would give lots of exciting
things to Emacs: native threads, a real object system, more
sophisticated types, cleaner syntax, and access to all of the Guile
extensions.

   Finally, there is another axis of crystallization, the axis between
different Scheme implementations.  Guile does not yet support the latest
Scheme standard, R6RS, and should do so.  Like all standards, R6RS is
imperfect, but supporting it will allow more code to run on Guile
without modification, and will allow Guile hackers to produce code
compatible with other schemes.  Help in this regard would be much
appreciated.


File: guile.info,  Node: Data Representation,  Next: A Virtual Machine for Guile,  Prev: History,  Up: Guile Implementation

9.2 Data Representation
=======================

Scheme is a latently-typed language; this means that the system cannot,
in general, determine the type of a given expression at compile time.
Types only become apparent at run time.  Variables do not have fixed
types; a variable may hold a pair at one point, an integer at the next,
and a thousand-element vector later.  Instead, values, not variables,
have fixed types.

   In order to implement standard Scheme functions like ‘pair?’ and
‘string?’ and provide garbage collection, the representation of every
value must contain enough information to accurately determine its type
at run time.  Often, Scheme systems also use this information to
determine whether a program has attempted to apply an operation to an
inappropriately typed value (such as taking the ‘car’ of a string).

   Because variables, pairs, and vectors may hold values of any type,
Scheme implementations use a uniform representation for values — a
single type large enough to hold either a complete value or a pointer to
a complete value, along with the necessary typing information.

   The following sections will present a simple typing system, and then
make some refinements to correct its major weaknesses.  We then conclude
with a discussion of specific choices that Guile has made regarding
garbage collection and data representation.

* Menu:

* A Simple Representation::     
* Faster Integers::             
* Cheaper Pairs::               
* Conservative GC::          
* The SCM Type in Guile::


File: guile.info,  Node: A Simple Representation,  Next: Faster Integers,  Up: Data Representation

9.2.1 A Simple Representation
-----------------------------

The simplest way to represent Scheme values in C would be to represent
each value as a pointer to a structure containing a type indicator,
followed by a union carrying the real value.  Assuming that ‘SCM’ is the
name of our universal type, we can write:

     enum type { integer, pair, string, vector, ... };

     typedef struct value *SCM;

     struct value {
       enum type type;
       union {
         int integer;
         struct { SCM car, cdr; } pair;
         struct { int length; char *elts; } string;
         struct { int length; SCM  *elts; } vector;
         ...
       } value;
     };
   with the ellipses replaced with code for the remaining Scheme types.

   This representation is sufficient to implement all of Scheme’s
semantics.  If X is an ‘SCM’ value:
   • To test if X is an integer, we can write ‘X->type == integer’.
   • To find its value, we can write ‘X->value.integer’.
   • To test if X is a vector, we can write ‘X->type == vector’.
   • If we know X is a vector, we can write ‘X->value.vector.elts[0]’ to
     refer to its first element.
   • If we know X is a pair, we can write ‘X->value.pair.car’ to extract
     its car.


File: guile.info,  Node: Faster Integers,  Next: Cheaper Pairs,  Prev: A Simple Representation,  Up: Data Representation

9.2.2 Faster Integers
---------------------

Unfortunately, the above representation has a serious disadvantage.  In
order to return an integer, an expression must allocate a ‘struct
value’, initialize it to represent that integer, and return a pointer to
it.  Furthermore, fetching an integer’s value requires a memory
reference, which is much slower than a register reference on most
processors.  Since integers are extremely common, this representation is
too costly, in both time and space.  Integers should be very cheap to
create and manipulate.

   One possible solution comes from the observation that, on many
architectures, heap-allocated data (i.e., what you get when you call
‘malloc’) must be aligned on an eight-byte boundary.  (Whether or not
the machine actually requires it, we can write our own allocator for
‘struct value’ objects that assures this is true.)  In this case, the
lower three bits of the structure’s address are known to be zero.

   This gives us the room we need to provide an improved representation
for integers.  We make the following rules:
   • If the lower three bits of an ‘SCM’ value are zero, then the SCM
     value is a pointer to a ‘struct value’, and everything proceeds as
     before.
   • Otherwise, the ‘SCM’ value represents an integer, whose value
     appears in its upper bits.

   Here is C code implementing this convention:
     enum type { pair, string, vector, ... };

     typedef struct value *SCM;

     struct value {
       enum type type;
       union {
         struct { SCM car, cdr; } pair;
         struct { int length; char *elts; } string;
         struct { int length; SCM  *elts; } vector;
         ...
       } value;
     };

     #define POINTER_P(x) (((int) (x) & 7) == 0)
     #define INTEGER_P(x) (! POINTER_P (x))

     #define GET_INTEGER(x)  ((int) (x) >> 3)
     #define MAKE_INTEGER(x) ((SCM) (((x) << 3) | 1))

   Notice that ‘integer’ no longer appears as an element of ‘enum type’,
and the union has lost its ‘integer’ member.  Instead, we use the
‘POINTER_P’ and ‘INTEGER_P’ macros to make a coarse classification of
values into integers and non-integers, and do further type testing as
before.

   Here’s how we would answer the questions posed above (again, assume X
is an ‘SCM’ value):
   • To test if X is an integer, we can write ‘INTEGER_P (X)’.
   • To find its value, we can write ‘GET_INTEGER (X)’.
   • To test if X is a vector, we can write:
            POINTER_P (X) && X->type == vector
     Given the new representation, we must make sure X is truly a
     pointer before we dereference it to determine its complete type.
   • If we know X is a vector, we can write ‘X->value.vector.elts[0]’ to
     refer to its first element, as before.
   • If we know X is a pair, we can write ‘X->value.pair.car’ to extract
     its car, just as before.

   This representation allows us to operate more efficiently on integers
than the first.  For example, if X and Y are known to be integers, we
can compute their sum as follows:
     MAKE_INTEGER (GET_INTEGER (X) + GET_INTEGER (Y))
   Now, integer math requires no allocation or memory references.  Most
real Scheme systems actually implement addition and other operations
using an even more efficient algorithm, but this essay isn’t about
bit-twiddling.  (Hint: how do you decide when to overflow to a bignum?
How would you do it in assembly?)


File: guile.info,  Node: Cheaper Pairs,  Next: Conservative GC,  Prev: Faster Integers,  Up: Data Representation

9.2.3 Cheaper Pairs
-------------------

However, there is yet another issue to confront.  Most Scheme heaps
contain more pairs than any other type of object; Jonathan Rees said at
one point that pairs occupy 45% of the heap in his Scheme
implementation, Scheme 48.  However, our representation above spends
three ‘SCM’-sized words per pair — one for the type, and two for the CAR
and CDR.  Is there any way to represent pairs using only two words?

   Let us refine the convention we established earlier.  Let us assert
that:
   • If the bottom three bits of an ‘SCM’ value are ‘#b000’, then it is
     a pointer, as before.
   • If the bottom three bits are ‘#b001’, then the upper bits are an
     integer.  This is a bit more restrictive than before.
   • If the bottom two bits are ‘#b010’, then the value, with the bottom
     three bits masked out, is the address of a pair.

   Here is the new C code:
     enum type { string, vector, ... };

     typedef struct value *SCM;

     struct value {
       enum type type;
       union {
         struct { int length; char *elts; } string;
         struct { int length; SCM  *elts; } vector;
         ...
       } value;
     };

     struct pair {
       SCM car, cdr;
     };

     #define POINTER_P(x) (((int) (x) & 7) == 0)

     #define INTEGER_P(x)  (((int) (x) & 7) == 1)
     #define GET_INTEGER(x)  ((int) (x) >> 3)
     #define MAKE_INTEGER(x) ((SCM) (((x) << 3) | 1))

     #define PAIR_P(x) (((int) (x) & 7) == 2)
     #define GET_PAIR(x) ((struct pair *) ((int) (x) & ~7))

   Notice that ‘enum type’ and ‘struct value’ now only contain
provisions for vectors and strings; both integers and pairs have become
special cases.  The code above also assumes that an ‘int’ is large
enough to hold a pointer, which isn’t generally true.

   Our list of examples is now as follows:
   • To test if X is an integer, we can write ‘INTEGER_P (X)’; this is
     as before.
   • To find its value, we can write ‘GET_INTEGER (X)’, as before.
   • To test if X is a vector, we can write:
            POINTER_P (X) && X->type == vector
     We must still make sure that X is a pointer to a ‘struct value’
     before dereferencing it to find its type.
   • If we know X is a vector, we can write ‘X->value.vector.elts[0]’ to
     refer to its first element, as before.
   • We can write ‘PAIR_P (X)’ to determine if X is a pair, and then
     write ‘GET_PAIR (X)->car’ to refer to its car.

   This change in representation reduces our heap size by 15%.  It also
makes it cheaper to decide if a value is a pair, because no memory
references are necessary; it suffices to check the bottom two bits of
the ‘SCM’ value.  This may be significant when traversing lists, a
common activity in a Scheme system.

   Again, most real Scheme systems use a slightly different
implementation; for example, if GET_PAIR subtracts off the low bits of
‘x’, instead of masking them off, the optimizer will often be able to
combine that subtraction with the addition of the offset of the
structure member we are referencing, making a modified pointer as fast
to use as an unmodified pointer.


File: guile.info,  Node: Conservative GC,  Next: The SCM Type in Guile,  Prev: Cheaper Pairs,  Up: Data Representation

9.2.4 Conservative Garbage Collection
-------------------------------------

Aside from the latent typing, the major source of constraints on a
Scheme implementation’s data representation is the garbage collector.
The collector must be able to traverse every live object in the heap, to
determine which objects are not live, and thus collectable.

   There are many ways to implement this.  Guile’s garbage collection is
built on a library, the Boehm-Demers-Weiser conservative garbage
collector (BDW-GC). The BDW-GC “just works”, for the most part.  But
since it is interesting to know how these things work, we include here a
high-level description of what the BDW-GC does.

   Garbage collection has two logical phases: a "mark" phase, in which
the set of live objects is enumerated, and a "sweep" phase, in which
objects not traversed in the mark phase are collected.  Correct
functioning of the collector depends on being able to traverse the
entire set of live objects.

   In the mark phase, the collector scans the system’s global variables
and the local variables on the stack to determine which objects are
immediately accessible by the C code.  It then scans those objects to
find the objects they point to, and so on.  The collector logically sets
a "mark bit" on each object it finds, so each object is traversed only
once.

   When the collector can find no unmarked objects pointed to by marked
objects, it assumes that any objects that are still unmarked will never
be used by the program (since there is no path of dereferences from any
global or local variable that reaches them) and deallocates them.

   In the above paragraphs, we did not specify how the garbage collector
finds the global and local variables; as usual, there are many different
approaches.  Frequently, the programmer must maintain a list of pointers
to all global variables that refer to the heap, and another list
(adjusted upon entry to and exit from each function) of local variables,
for the collector’s benefit.

   The list of global variables is usually not too difficult to
maintain, since global variables are relatively rare.  However, an
explicitly maintained list of local variables (in the author’s personal
experience) is a nightmare to maintain.  Thus, the BDW-GC uses a
technique called "conservative garbage collection", to make the local
variable list unnecessary.

   The trick to conservative collection is to treat the stack as an
ordinary range of memory, and assume that _every_ word on the stack is a
pointer into the heap.  Thus, the collector marks all objects whose
addresses appear anywhere in the stack, without knowing for sure how
that word is meant to be interpreted.

   In addition to the stack, the BDW-GC will also scan static data
sections.  This means that global variables are also scanned when
looking for live Scheme objects.

   Obviously, such a system will occasionally retain objects that are
actually garbage, and should be freed.  In practice, this is not a
problem.  The alternative, an explicitly maintained list of local
variable addresses, is effectively much less reliable, due to programmer
error.  Interested readers should see the BDW-GC web page at
<http://www.hpl.hp.com/personal/Hans_Boehm/gc>, for more information.


File: guile.info,  Node: The SCM Type in Guile,  Prev: Conservative GC,  Up: Data Representation

9.2.5 The SCM Type in Guile
---------------------------

Guile classifies Scheme objects into two kinds: those that fit entirely
within an ‘SCM’, and those that require heap storage.

   The former class are called "immediates".  The class of immediates
includes small integers, characters, boolean values, the empty list, the
mysterious end-of-file object, and some others.

   The remaining types are called, not surprisingly, "non-immediates".
They include pairs, procedures, strings, vectors, and all other data
types in Guile.  For non-immediates, the ‘SCM’ word contains a pointer
to data on the heap, with further information about the object in
question is stored in that data.

   This section describes how the ‘SCM’ type is actually represented and
used at the C level.  Interested readers should see ‘libguile/tags.h’
for an exposition of how Guile stores type information.

   In fact, there are two basic C data types to represent objects in
Guile: ‘SCM’ and ‘scm_t_bits’.

* Menu:

* Relationship between SCM and scm_t_bits::
* Immediate objects::
* Non-immediate objects::
* Allocating Cells::
* Heap Cell Type Information::
* Accessing Cell Entries::


File: guile.info,  Node: Relationship between SCM and scm_t_bits,  Next: Immediate objects,  Up: The SCM Type in Guile

9.2.5.1 Relationship between ‘SCM’ and ‘scm_t_bits’
...................................................

A variable of type ‘SCM’ is guaranteed to hold a valid Scheme object.  A
variable of type ‘scm_t_bits’, on the other hand, may hold a
representation of a ‘SCM’ value as a C integral type, but may also hold
any C value, even if it does not correspond to a valid Scheme object.

   For a variable X of type ‘SCM’, the Scheme object’s type information
is stored in a form that is not directly usable.  To be able to work on
the type encoding of the scheme value, the ‘SCM’ variable has to be
transformed into the corresponding representation as a ‘scm_t_bits’
variable Y by using the ‘SCM_UNPACK’ macro.  Once this has been done,
the type of the scheme object X can be derived from the content of the
bits of the ‘scm_t_bits’ value Y, in the way illustrated by the example
earlier in this chapter (*note Cheaper Pairs::).  Conversely, a valid
bit encoding of a Scheme value as a ‘scm_t_bits’ variable can be
transformed into the corresponding ‘SCM’ value using the ‘SCM_PACK’
macro.


File: guile.info,  Node: Immediate objects,  Next: Non-immediate objects,  Prev: Relationship between SCM and scm_t_bits,  Up: The SCM Type in Guile

9.2.5.2 Immediate objects
.........................

A Scheme object may either be an immediate, i.e. carrying all necessary
information by itself, or it may contain a reference to a "cell" with
additional information on the heap.  Although in general it should be
irrelevant for user code whether an object is an immediate or not,
within Guile’s own code the distinction is sometimes of importance.
Thus, the following low level macro is provided:

 -- Macro: int SCM_IMP (SCM X)
     A Scheme object is an immediate if it fulfills the ‘SCM_IMP’
     predicate, otherwise it holds an encoded reference to a heap cell.
     The result of the predicate is delivered as a C style boolean
     value.  User code and code that extends Guile should normally not
     be required to use this macro.

Summary:
   • Given a Scheme object X of unknown type, check first with ‘SCM_IMP
     (X)’ if it is an immediate object.
   • If so, all of the type and value information can be determined from
     the ‘scm_t_bits’ value that is delivered by ‘SCM_UNPACK (X)’.

   There are a number of special values in Scheme, most of them
documented elsewhere in this manual.  It’s not quite the right place to
put them, but for now, here’s a list of the C names given to some of
these values:

 -- Macro: SCM SCM_EOL
     The Scheme empty list object, or “End Of List” object, usually
     written in Scheme as ‘'()’.

 -- Macro: SCM SCM_EOF_VAL
     The Scheme end-of-file value.  It has no standard written
     representation, for obvious reasons.

 -- Macro: SCM SCM_UNSPECIFIED
     The value returned by some (but not all) expressions that the
     Scheme standard says return an “unspecified” value.

     This is sort of a weirdly literal way to take things, but the
     standard read-eval-print loop prints nothing when the expression
     returns this value, so it’s not a bad idea to return this when you
     can’t think of anything else helpful.

 -- Macro: SCM SCM_UNDEFINED
     The “undefined” value.  Its most important property is that is not
     equal to any valid Scheme value.  This is put to various internal
     uses by C code interacting with Guile.

     For example, when you write a C function that is callable from
     Scheme and which takes optional arguments, the interpreter passes
     ‘SCM_UNDEFINED’ for any arguments you did not receive.

     We also use this to mark unbound variables.

 -- Macro: int SCM_UNBNDP (SCM X)
     Return true if X is ‘SCM_UNDEFINED’.  Note that this is not a check
     to see if X is ‘SCM_UNBOUND’.  History will not be kind to us.


File: guile.info,  Node: Non-immediate objects,  Next: Allocating Cells,  Prev: Immediate objects,  Up: The SCM Type in Guile

9.2.5.3 Non-immediate objects
.............................

A Scheme object of type ‘SCM’ that does not fulfill the ‘SCM_IMP’
predicate holds an encoded reference to a heap cell.  This reference can
be decoded to a C pointer to a heap cell using the ‘SCM2PTR’ macro.  The
encoding of a pointer to a heap cell into a ‘SCM’ value is done using
the ‘PTR2SCM’ macro.

 -- Macro: scm_t_cell * SCM2PTR (SCM X)
     Extract and return the heap cell pointer from a non-immediate ‘SCM’
     object X.

 -- Macro: SCM PTR2SCM (scm_t_cell * X)
     Return a ‘SCM’ value that encodes a reference to the heap cell
     pointer X.

   Note that it is also possible to transform a non-immediate ‘SCM’
value by using ‘SCM_UNPACK’ into a ‘scm_t_bits’ variable.  However, the
result of ‘SCM_UNPACK’ may not be used as a pointer to a ‘scm_t_cell’:
only ‘SCM2PTR’ is guaranteed to transform a ‘SCM’ object into a valid
pointer to a heap cell.  Also, it is not allowed to apply ‘PTR2SCM’ to
anything that is not a valid pointer to a heap cell.

Summary:
   • Only use ‘SCM2PTR’ on ‘SCM’ values for which ‘SCM_IMP’ is false!
   • Don’t use ‘(scm_t_cell *) SCM_UNPACK (X)’!  Use ‘SCM2PTR (X)’
     instead!
   • Don’t use ‘PTR2SCM’ for anything but a cell pointer!


File: guile.info,  Node: Allocating Cells,  Next: Heap Cell Type Information,  Prev: Non-immediate objects,  Up: The SCM Type in Guile

9.2.5.4 Allocating Cells
........................

Guile provides both ordinary cells with two slots, and double cells with
four slots.  The following two function are the most primitive way to
allocate such cells.

   If the caller intends to use it as a header for some other type, she
must pass an appropriate magic value in WORD_0, to mark it as a member
of that type, and pass whatever value as WORD_1, etc that the type
expects.  You should generally not need these functions, unless you are
implementing a new datatype, and thoroughly understand the code in
‘<libguile/tags.h>’.

   If you just want to allocate pairs, use ‘scm_cons’.

 -- Function: SCM scm_cell (scm_t_bits word_0, scm_t_bits word_1)
     Allocate a new cell, initialize the two slots with WORD_0 and
     WORD_1, and return it.

     Note that WORD_0 and WORD_1 are of type ‘scm_t_bits’.  If you want
     to pass a ‘SCM’ object, you need to use ‘SCM_UNPACK’.

 -- Function: SCM scm_double_cell (scm_t_bits word_0, scm_t_bits word_1,
          scm_t_bits word_2, scm_t_bits word_3)
     Like ‘scm_cell’, but allocates a double cell with four slots.


File: guile.info,  Node: Heap Cell Type Information,  Next: Accessing Cell Entries,  Prev: Allocating Cells,  Up: The SCM Type in Guile

9.2.5.5 Heap Cell Type Information
..................................

Heap cells contain a number of entries, each of which is either a scheme
object of type ‘SCM’ or a raw C value of type ‘scm_t_bits’.  Which of
the cell entries contain Scheme objects and which contain raw C values
is determined by the first entry of the cell, which holds the cell type
information.

 -- Macro: scm_t_bits SCM_CELL_TYPE (SCM X)
     For a non-immediate Scheme object X, deliver the content of the
     first entry of the heap cell referenced by X.  This value holds the
     information about the cell type.

 -- Macro: void SCM_SET_CELL_TYPE (SCM X, scm_t_bits T)
     For a non-immediate Scheme object X, write the value T into the
     first entry of the heap cell referenced by X.  The value T must
     hold a valid cell type.


File: guile.info,  Node: Accessing Cell Entries,  Prev: Heap Cell Type Information,  Up: The SCM Type in Guile

9.2.5.6 Accessing Cell Entries
..............................

For a non-immediate Scheme object X, the object type can be determined
by reading the cell type entry using the ‘SCM_CELL_TYPE’ macro.  For
each different type of cell it is known which cell entries hold Scheme
objects and which cell entries hold raw C data.  To access the different
cell entries appropriately, the following macros are provided.

 -- Macro: scm_t_bits SCM_CELL_WORD (SCM X, unsigned int N)
     Deliver the cell entry N of the heap cell referenced by the
     non-immediate Scheme object X as raw data.  It is illegal, to
     access cell entries that hold Scheme objects by using these macros.
     For convenience, the following macros are also provided.
        • SCM_CELL_WORD_0 (X) ⇒ SCM_CELL_WORD (X, 0)
        • SCM_CELL_WORD_1 (X) ⇒ SCM_CELL_WORD (X, 1)
        • …
        • SCM_CELL_WORD_N (X) ⇒ SCM_CELL_WORD (X, N)

 -- Macro: SCM SCM_CELL_OBJECT (SCM X, unsigned int N)
     Deliver the cell entry N of the heap cell referenced by the
     non-immediate Scheme object X as a Scheme object.  It is illegal,
     to access cell entries that do not hold Scheme objects by using
     these macros.  For convenience, the following macros are also
     provided.
        • SCM_CELL_OBJECT_0 (X) ⇒ SCM_CELL_OBJECT (X, 0)
        • SCM_CELL_OBJECT_1 (X) ⇒ SCM_CELL_OBJECT (X, 1)
        • …
        • SCM_CELL_OBJECT_N (X) ⇒ SCM_CELL_OBJECT (X, N)

 -- Macro: void SCM_SET_CELL_WORD (SCM X, unsigned int N, scm_t_bits W)
     Write the raw C value W into entry number N of the heap cell
     referenced by the non-immediate Scheme value X.  Values that are
     written into cells this way may only be read from the cells using
     the ‘SCM_CELL_WORD’ macros or, in case cell entry 0 is written,
     using the ‘SCM_CELL_TYPE’ macro.  For the special case of cell
     entry 0 it has to be made sure that W contains a cell type
     information which does not describe a Scheme object.  For
     convenience, the following macros are also provided.
        • SCM_SET_CELL_WORD_0 (X, W) ⇒ SCM_SET_CELL_WORD (X, 0, W)
        • SCM_SET_CELL_WORD_1 (X, W) ⇒ SCM_SET_CELL_WORD (X, 1, W)
        • …
        • SCM_SET_CELL_WORD_N (X, W) ⇒ SCM_SET_CELL_WORD (X, N, W)

 -- Macro: void SCM_SET_CELL_OBJECT (SCM X, unsigned int N, SCM O)
     Write the Scheme object O into entry number N of the heap cell
     referenced by the non-immediate Scheme value X.  Values that are
     written into cells this way may only be read from the cells using
     the ‘SCM_CELL_OBJECT’ macros or, in case cell entry 0 is written,
     using the ‘SCM_CELL_TYPE’ macro.  For the special case of cell
     entry 0 the writing of a Scheme object into this cell is only
     allowed if the cell forms a Scheme pair.  For convenience, the
     following macros are also provided.
        • SCM_SET_CELL_OBJECT_0 (X, O) ⇒ SCM_SET_CELL_OBJECT (X, 0, O)
        • SCM_SET_CELL_OBJECT_1 (X, O) ⇒ SCM_SET_CELL_OBJECT (X, 1, O)
        • …
        • SCM_SET_CELL_OBJECT_N (X, O) ⇒ SCM_SET_CELL_OBJECT (X, N, O)

Summary:
   • For a non-immediate Scheme object X of unknown type, get the type
     information by using ‘SCM_CELL_TYPE (X)’.
   • As soon as the cell type information is available, only use the
     appropriate access methods to read and write data to the different
     cell entries.


File: guile.info,  Node: A Virtual Machine for Guile,  Next: Compiling to the Virtual Machine,  Prev: Data Representation,  Up: Guile Implementation

9.3 A Virtual Machine for Guile
===============================

Guile has both an interpreter and a compiler.  To a user, the difference
is transparent—interpreted and compiled procedures can call each other
as they please.

   The difference is that the compiler creates and interprets bytecode
for a custom virtual machine, instead of interpreting the S-expressions
directly.  Loading and running compiled code is faster than loading and
running source code.

   The virtual machine that does the bytecode interpretation is a part
of Guile itself.  This section describes the nature of Guile’s virtual
machine.

* Menu:

* Why a VM?::                   
* VM Concepts::                 
* Stack Layout::                
* Variables and the VM::                   
* VM Programs::         
* Instruction Set::


File: guile.info,  Node: Why a VM?,  Next: VM Concepts,  Up: A Virtual Machine for Guile

9.3.1 Why a VM?
---------------

For a long time, Guile only had an interpreter.  Guile’s interpreter
operated directly on the S-expression representation of Scheme source
code.

   But while the interpreter was highly optimized and hand-tuned, it
still performs many needless computations during the course of
evaluating an expression.  For example, application of a function to
arguments needlessly consed up the arguments in a list.  Evaluation of
an expression always had to figure out what the car of the expression is
– a procedure, a memoized form, or something else.  All values have to
be allocated on the heap.  Et cetera.

   The solution to this problem was to compile the higher-level
language, Scheme, into a lower-level language for which all of the
checks and dispatching have already been done—the code is instead
stripped to the bare minimum needed to “do the job”.

   The question becomes then, what low-level language to choose?  There
are many options.  We could compile to native code directly, but that
poses portability problems for Guile, as it is a highly cross-platform
project.

   So we want the performance gains that compilation provides, but we
also want to maintain the portability benefits of a single code path.
The obvious solution is to compile to a virtual machine that is present
on all Guile installations.

   The easiest (and most fun) way to depend on a virtual machine is to
implement the virtual machine within Guile itself.  This way the virtual
machine provides what Scheme needs (tail calls, multiple values,
‘call/cc’) and can provide optimized inline instructions for Guile
(‘cons’, ‘struct-ref’, etc.).

   So this is what Guile does.  The rest of this section describes that
VM that Guile implements, and the compiled procedures that run on it.

   Before moving on, though, we should note that though we spoke of the
interpreter in the past tense, Guile still has an interpreter.  The
difference is that before, it was Guile’s main evaluator, and so was
implemented in highly optimized C; now, it is actually implemented in
Scheme, and compiled down to VM bytecode, just like any other program.
(There is still a C interpreter around, used to bootstrap the compiler,
but it is not normally used at runtime.)

   The upside of implementing the interpreter in Scheme is that we
preserve tail calls and multiple-value handling between interpreted and
compiled code.  The downside is that the interpreter in Guile 2.0 is
slower than the interpreter in 1.8.  We hope the that the compiler’s
speed makes up for the loss!

   Also note that this decision to implement a bytecode compiler does
not preclude native compilation.  We can compile from bytecode to native
code at runtime, or even do ahead of time compilation.  More
possibilities are discussed in *note Extending the Compiler::.

