In-line Coding - MIT/GNU Scheme 9.0
Description: MIT/GNU Scheme 9.0

Next: Replacement of Operators, Previous: Standard Names, Up: Declarations

#### 4.2.2 In-line Coding

Another useful facility is the ability to in-line code procedure definitions. In fact, the compiler will perform full beta conversion, with automatic renaming, if you request it. Here are the relevant declarations:

— declaration: integrate name ...

> The variables names must be defined in the same file as this declaration. Any reference to one of the named variables that appears in the same block as the declaration, or one of its descendant blocks, will be replaced by the corresponding binding's value expression.

— declaration: integrate-operator name ...

> Similar to the `integrate` declaration, except that it only substitutes for references that appear in the operator position of a combination. All other references are ignored.

— declaration: integrate-external filename

> Causes the compiler to use the top-level integrations provided by filename. filename should not specify a file type, and the source-code file that it names must have been previously processed by the compiler.

> If filename is a relative filename (the normal case), it is interpreted as being relative to the file in which the declaration appears. Thus if the declaration appears in file `/usr/cph/foo.scm`, then the compiler looks for a file called `/usr/cph/filename.ext`.

> Note: When the compiler finds top-level integrations, it collects them and outputs them into an auxiliary file with extension `.ext`. This `.ext` file is what the `integrate-external` declaration refers to.

Note that the most common use of this facility, in-line coding of procedure definitions, requires a somewhat complicated use of these declarations. Because this is so common, there is a special form, `define-integrable`, which is like `define` but performs the appropriate declarations. For example:

         (define-integrable (foo-bar foo bar)
           (vector-ref (vector-ref foo bar) 3))

Here is how you do the same thing without this special form: there should be an `integrate-operator` declaration for the procedure's name, and (internal to the procedure's definition) an `integrate` declaration for each of the procedure's parameters, like this:

         (declare (integrate-operator foo-bar))

         (define foo-bar
           (lambda (foo bar)
             (declare (integrate foo bar))
             (vector-ref (vector-ref foo bar) 3)))

The reason for this complication is as follows: the `integrate-operator` declaration finds all the references to `foo-bar` and replaces them with the lambda expression from the definition. Then, the `integrate` declarations take effect because the combination in which the reference to `foo-bar` occurred supplies code that is substituted throughout the body of the procedure definition. For example:

         (foo-bar (car baz) (cdr baz))

First use the `integrate-operator` declaration:

         ((lambda (foo bar)
            (declare (integrate foo bar))
            (vector-ref (vector-ref foo bar) 3))
          (car baz)
          (cdr baz))

Next use the internal `integrate` declaration:

         ((lambda (foo bar)
            (vector-ref (vector-ref (car baz) (cdr baz)) 3))
          (car baz)
          (cdr baz))

Next notice that the variables `foo` and `bar` are not used, and eliminate them:

         ((lambda ()
            (vector-ref (vector-ref (car baz) (cdr baz)) 3)))

Finally, remove the ‘`((lambda () ...))`’ to produce

         (vector-ref (vector-ref (car baz) (cdr baz)) 3)

##### Useful tip

To see the effect of integration declarations (and of macros) on a source file, pretty-print the `.bin` file like this (be prepared for a lot of output).

         (sf "foo.scm")
         (pp (fasload "foo.bin"))