[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Scheme-reports] loading libraries

On Fri, Oct 25, 2013 at 1:16 AM, Michael Montague <mikemon@x> wrote:
When I first implemented support for libraries I thought that it was required that each time a library was imported it had to be loaded which seemed weird; obviously, I had not read the specification closely enough. When I realized why parameters were not working, I went back and read the specification much more closely, and then fixed my library support to load libraries only once.

Why is the specification vague about how many times libraries get loaded? As a user of scheme, it would be much clearer to me to be able to look at a library and know that it was going to be loaded exactly once.

The specification is vague because the popular implementations
actually differ in how they behave.  R7RS tends to be descriptive
rather than prescriptive - it is to a large extent describing the
"de facto" standard Scheme that exists today.

The purpose of doing this is to establish a common ground so
that the multiple Scheme communities can share code.  There
are many useful libraries and programs that can be written
completely independently of the number of times a library is

It would also be useful to have a standard that removes some
or all of the unspecified parts of R7RS.  The large language
may in fact provide some form of feature-identified language
levels, or R8RS may tighten things down further.

If you're asking why implementations exist that load libraries
multiple times, Sam hinted at the reason, which is that it has
to do with phasing (the distinction between run time and compile
time).  Specifically, if you have low-level macros which make
use of shared compile time state, then the expansions may
differ depending on whether or not you use separate compilation,
or on the order of compilation, which generally indicates a bug.
Establishing a separate hierarchy of compile-time environments
(with their own instantiations of imported libraries), prevents
such differences.

Other implementations simply leave avoiding these bugs up
to the programmer.

So to answer your original question, the program you wrote
would not actually cause load multiple loads on any existing
implementation.  You need to invoke compile-time phasing
(require (for-syntax ...)) to cause this, and even then I believe
after everything is compiled all the runtime bindings will be
the same.

But because the small language does not need a phase distinction
we simply noted that libraries may be loaded multiple times,
without further restrictions.  The large language will introduce
low-level macros and phasing.


On 10/24/2013 6:28 AM, Sam Tobin-Hochstadt wrote:
No implementation, to my knowledge, has ever loaded libraries multiple
times in the example you gave.  Racket loads modules separately for
each modules's compilation, because each compilation of a single
module has its own store, not shared with runtime or any other

This modification of your program shows an aspect of Racket's behavior
-- it writes `(small cake)`.

#lang racket/load

(module |(bakery size)| racket
   (provide size)
   (define size (make-parameter 'small)))

(module |(bakery cake)| racket
   (require (for-syntax '|(bakery size)|))
   (provide make-cake)
     (define-syntax (make-cake stx)
          #,(list (size) 'cake)))))

;; program
(require '|(bakery size)|)
(require '|(bakery cake)|)

(parameterize ((size 'large)) (write (make-cake)))

On Thu, Oct 24, 2013 at 12:33 AM, Michael Montague <mikemon@x> wrote:
On 10/23/2013 6:12 PM, Alex Shinn wrote:
The libraries may in fact be loaded multiple times,
to allow for models such as Racket which require
clean environments for each library expansion in
order to avoid unwanted macro interactions.

I don't understand how parameters work in implementations where
libraries can be loaded more than once.

In the following example, each time (bakery size) is loaded, size will
be bound to a different parameter. An implementation that loads
libraries each time they are imported would write (small cake). And an
implementation which loads libraries only once would write (large cake).

(define-library (bakery size)
      (import (scheme base))
      (export size)
          (define size (make-parameter 'small))))

(define-library (bakery cake)
      (import (scheme base))
      (import (bakery size))
      (export make-cake)
          (define (make-cake)
              (list (size) 'cake))))

;; program
(import (scheme base))
(import (scheme write))
(import (bakery size))
(import (bakery cake))

(parameterize ((size 'large)) (write (make-cake)))

Scheme-reports mailing list

Scheme-reports mailing list