Scheme Load Return Values
Shortly after finishing my previous post, I began to wonder if maybe some of the features I had requested were available already. I was pleasantly surprised.
Implementations tested were:
Bad news first. In my hour or so of testing, I was unable to find any way to directly return values from a loaded file in Guile, Gambit, and STklos.
On the other hand, that means that four of the seven implementations that I tested could return values.
MzScheme and MIT Scheme both return the last form, whatever it was. If the last form was a DEFINE statement, MzScheme returns nothing, and MIT Scheme returns the identifier that was defined.
Bigloo doesn't seem to return anything usable, but it does print the results of intermediate evaluations, and claims to return the result of the last evaluation. This may indeed be true, but in my testing I was unable to get it to return anything other than the path of the just-loaded file.
Chicken, however, was an unqualified success. Although it is true that at first it returns nothing from its LOAD function, it provides a brilliant little mechanism to fix that. The LOAD function, in addition to taking a filename, will also take an optional argument called EVALPROC, which is called repeatedly with each form from the loaded file. This fact, combined with a little closure magic, ends us up with this:
(let ((return '()))
(load file
(lambda (exp)
(if (and (list? exp) (eqv? (list-ref exp 0) 'define))
(begin
(eval exp)
(set! return (cons (list-ref exp 1) return)))
(set! return (cons (eval exp) return)))))
(reverse return)))
This function calls the LOAD function, but passes it its own evaluation procedure, which will assemble a list of values when called, as well as evaluating each expression.
After seeing the beautiful and elegant way in which Chicken Scheme allows the user to dynamically alter the behaviour of the LOAD function at runtime, I feel like I should alter my recommendation for modifying that behaviour. Chicken has, I believe, found the best possible way to implement such functionality: have a reasonable default, but allow people to override it if they wish. Simple, elegant, and powerful: exactly like the language itself. Bravo, Chicken.
Bravo.
SoLoad Progression
When I first created SoLoad, I intended to just make available C libraries and functionality, at which point I would be done with the project. But now the scope seems to have grown.
SoLoad has been, if not entirely rewritten, at least extensively renovated. It now uses a plugin architecture, and a concept of "interfaces" which implement a certain set of functionality for a programming language or API.
The C interface retains feature-parity with where it was before the recent changes (but the names of commands have changed) and the Python interface is capable of rudimentary operations.
Yes, that is correct. Python.
The new plugin architecture allows different languages and calling conventions to coexist within the same program. The interfaces to different languages are each encapsulated in their own shared object file, making it possible to, for example, compile a plugin which embeds a python interpreter and then use that interpreter to act upon data calculated by a C function.
Currently, the Python plugin is capable of loading modules, extracting a function, and executing said function, but only if the function takes a single integer argument and returns another integer. Over the next few days, I intend to flesh out the type conversion routines so that any Python function can be executed.
Other languages being considered for support include:
- Common Lisp (through ECL)
- Scheme (through MzScheme)
- Java (through JNI)
And now I get to rewrite all the documentation. Again.












