I implemented a basic scheme (think SICP). Now, I'd like to add a basic import/library functionality but have trouble coming up with a way to do that. I considered two approaches so far both suffering from the same obstacle.
In the old SICP (edition one) book there was a make-environment / package chapter which was also discussed here. This returns a new environment.
I would like to call something like
(import lib)
where lib either provides an environment or a list of procedure names and procedures. The question I have is how to programmatically extend the current environment with procedures that are provided by the library. Using something like a
((lambda (name proc) (define name proc)) 'test (lambda a (+ a a)))
is not going to work since define
can not create a binding that is outside the scope of the lambda
.
I have looked at the reference implementation of r6rs but was not able to figure out what the underlying mechanism for import
is. How does it create the binding?
update 1
I think the underlying question (issue) I have is that it's not possible to use define
within a lambda
since the modification of the environment done through define
is limited to the scope of the surrounding lambda
. Is there a why programmatically define
multiple (for example generated) procedures.
This works (similar to what is described here):
((eval `square-rrot scientific-lib) 4)
and this
(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 can not define them one by one, I'd need a programmatic way to do that but I can not use something like:
((lambda (newName, libName) (define newName (eval libName scientific-lib))) sqrt `square-root)
It seems to me after reading the comments and answers that it is not possible based in stuff presented in SIPC. One needs more advanced stuff like define-syntax
. Or am I wrong?
Here is how I did it in the end. Basically I departed from scheme and added a flag to lambda. A lambda can then either be scoped or not. The scoped lambda behaves as the usual lambda. In the case the lambda is not scoped I evaluate the body in an empty environment. This is then evaluated in the current environment. Something like this: