Simple library mechanism for schema implementation - import

I have implemented a basic circuit (SICP think). Now I would like to add basic import / library functionality, but I am having trouble being able to do so. I've considered two approaches so far, both suffer from the same obstacle.

The old SICP book (revision 1) has a chapter make-environment / package, which was also discussed here. This brings back a new environment.

I would like to name something like

(import lib)

      

where lib provides an environment or list of procedure names and procedures. I have a question on how to programmatically extend the current environment using the procedures provided by the library. Using something like

((lambda (name proc) (define name proc)) 'test (lambda a (+ a a)))

      

won't work because define

it can't create a binding that goes out of scope lambda

.

I looked at the referenced implementation of r6rs but couldn't figure out what the underlying mechanism is for import

. How do I create a binding?

update 1

I think the main question (question) I have is that it is not possible to use define

within lambda

, since the modification of the environment done through define

is limited to the scope of the environment lambda

, Is there any reason for programmatic define

multiple (e.g. generated) procedures.

This works (similar to what is described here ):

((eval `square-rrot scientific-lib) 4)

      

and this one

(eval `(square-rrot 4) scientific-lib)

      

I can even write

(define sqrt (eval `square-root scientific-lib))

      

The above, however, is not sustainable. If I have a lib with 100 functions, I cannot define them one by one, I need a programmatic way to do it, but I cannot use something like:

((lambda (newName, libName) (define newName (eval libName scientific-lib))) sqrt `square-root)

      

It seems to me, after reading the comments and responses, that this is not possible in the materials submitted to the SIPC. Looking for more advanced things like define-syntax

. Or am I wrong?

+3


source to share


2 answers


This is how I did it at the end. I basically went away from the schema and added a flag to the lambda. Then the lambda can be limited or not. A region lambda behaves like a regular lambda. In the case where the lambda is not covered, I evaluate the body in an empty environment. This is then evaluated in the current environment. Something like that:



    if (lambdaHasAttribute(lambda, SCOPED)) {
        eenv = environment_extend(parameter, arguments, lambda_env);
        tmp = eval(lambda_body, eenv);
    } else {
        eenv = environment_extend(parameter, arguments, , mk_environment());
        /* scope arguments */
        tmp = eval(lambda_body, eenv);
        /* evaluate unscoped */
        tmp = eval(tmp, global_env);
    }

      

0


source


So your library just has to become a bunch of evaluable forms that have a local environment as in the definition. The value created by the library will be some kind of object added to the global list of available libraries, which will have names along with their values ​​(procedures, syntax, etc.) for export.

The import usually has a lot of functionality, but in reality it only takes a library object and inserts the attachment it wants into a frame and puts the program / library body in that frame.

You can do a rough implementation of the library in Scheme, but while you can't change the environment frames, you can easily specify what you need to import:



;; crude library support made with 
;; syntax rules and closures
#!r6rs
(import (rnrs base)
        (only (srfi :1) filter any))

(define-syntax lib
  (syntax-rules ()
    ((_ name (export-symbols ...) body ...)
     (define name
       (let ()
         ; make the defines local
         ; here you import other libraries
         body ... 

         ;; ^binds is a assoc between symbols and
         ;; implementation. 
         (define ^binds
           (list (cons 'export-symbols export-symbols) ...))

         ;; the function to leak definitions
         (lambda args
           (apply values 
                  (map cdr 
                       (filter 
                        (lambda (x)
                          (any (lambda (e)
                                 (eq? e (car x)))
                               args))
                        ^binds)))))))))

(define-syntax imp
  (syntax-rules ()
    ((_ name sym1)
     (define sym1 (name 'sym1)))
    ((_ name symn ...)
     (begin
       (imp name symn) ...))))

;; test
(lib test (add sub)
     (define (add a b)
       (sub a (sub 0 b)))
     (define (sub a b)
       (- a b)))

(imp test add)
(add 5 3) ; ==> 8

      

It doesn't look like it, but add

uses sub

from the same library which is not available globally since we didn't import it. You see? You can have private (non-exported) procedures as well.

Basic operations are the procedure for leaking the closure parts created by the library form, and the same idea as when passing a message. (one way to do OOP on a schematic)

+1


source







All Articles