[plt-scheme] eval, modules, namespaces, servlet ... um help?

From: Michael Forster (mike at sharedlogic.ca)
Date: Sun Jun 8 17:50:26 EDT 2008

Hi,

I'm in a bit of pickle. Any help would be greatly appreciated.

I've written a REL.SS module that maintains a database by
serializing/deserializing database transactions to/from disk (using
PLT's SERIALIZE.SS).

A transaction is a list of a symbol naming the database update procedure
followed by the name of the table to update and some update-specific
args.  For example, as serialized to disk:

  (0 () 0 () () (c! tx-delete/by-key c! customer-contact c! (c!
contact-no c! 13)))
  (0 () 0 () () (c! tx-delete/all c! customer-contact c! ()))

In REL.SS (shown below), to reload a database, I first read and deserialize
the transactions from disk, then I evaluate the car of each resulting list to
obtain the update procedure, and then I call that procedure on the database
table and update arguments (also from the list).  Basically, I replay the
transactions.

In SERVLET.SS (shown below), I have written a servlet (using
INSTASERVLET.SS, slightly hacked to work with v372) that queries the
user for customer data and inserts the data into the customer database
table using execute-transaction and tx-insert from REL.SS.

If I open up and run SERVLET.SS in DrScheme, then type

  (go! servlet)

the servlet loads okay, and I can fill out the customer entry form, but
when I submit it, the call to execute-transaction fails with the following
message:

  rel.ss::50317: Servlet exception:
  reference to undefined identifier: tx-insert

My understanding is that the eval call in REL.SS below can't identify
the tx-insert procedure in the 'current namespace', even though
tx-insert is defined in the same module where the eval call takes
place.

However, if I open up and run SERVLET.SS in DrScheme, then type

  (require "model.ss" "rel.ss" "instaservlet.ss" "obo-ems-insta.ss")
  (execute-transaction db 'tx-insert 'customer (list (make-tuple ...)))

it works.  Clearly, tx-insert can be identified in the 'current namespace'
in this case, and it seems to me that the namespace is different than
the when running the servlet.

So, what namespace or environment do I pass to eval to make this work?
Or do I need to configure instaservlet to load/require REL.SS?  I've
looked at http://schemecookbook.org/Cookbook/DynamicEvalCustomNamespace,
but I'm stabbing in the dark at this point, and I  sure could use a flashlight.

Thanks in advance for any help!

-Mike


;; REL.SS
(module rel mzscheme

  (require ...)

  (provide ... tx-insert execute-transaction ...)

  (define tx-insert
    (lambda (r arglist) ...)

  (define execute-transaction
    (lambda (db proc-name relvar-name arglist)
      (let ((r ((eval proc-name)
                (hash-table-get (database-relvars db) relvar-name)
                arglist)))
         ...)))


;; SERVLET.SS
#lang mzscheme

(require ... "rel.ss" "instaservlet.ss" ...)

(define db (make-database ...))

(define create/customer
  (lambda ()
    (let ((results (query/form ...)))
      (if results
        (execute-transaction db 'tx-insert 'customer (list (make-tuple
results)))
        #f))))

(define servlet
  (lambda (initial-request)
    (create/customer)))


Posted on the users mailing list.