From: Ken A. <kan...@bb...> - 2004-10-29 21:17:12
|
{ One of the nice things Scheme is good for is writing embedded minilangauges. You can write a lot less code if you tailor such languages for your application. For example, since you main a triathlon sight a common idiom might be to do a database lookup and generate HTML. Here's one way to do it, there are many others. Also, i cut some corners. There is a lot going on in this example, so its OK if you don't understand it right a way. } (load "elf/jdbc.scm") (load "elf/html-gen.scm") (java.sql.DriverManager.registerDriver (oracle.jdbc.driver.OracleDriver.)) ;;; dbConnection: -> java.sql.Connection (define (dbConnection) (DriverManager.getConnection dbUrl dbUser dbPassword)) ;;; withDbConnection: Connection thunk -> Object (define (withDbConnection con action) ;; Action is a procedure with a Connection argument. ;; The connection is closed when this returns. (tryCatch (Procedure.tryFinally (lambda () (action con)) (lambda () (.close con))) (lambda (e) (print e)(.close con)))) { Here is a simple macro. I use collect-query for simplicity. } (define-macro (mapQuery con query args . body) `(withDbConnection ,con (let ((f (lambda ,args ,@body))) (lambda (con) (map (lambda (row) (apply f (array->list row))) (cdr (collect-query con ,query))))))) { Here's an example of using the macro. It uses the <> macro for generating HTML. So we're mixing Scheme, JScheme's quasi-string and 2 embedded languages here. While this example doesn't show it, <> also uses quasquote so there is 1 language (scheme) and 4 sublanguages used here. This sounds pretty complicated, but our experience is that it has worked pretty well. } (define (runwayData icao) (<> p {Airport [icao] has runways:} (<> table (<> tr (<> td "High") (<> td "Low") (<> td "Length")) (mapQuery (dbConnection) {select r.high_ident, r.low_ident, r.length from runway r, airport a where r.arpt_ident = a.arpt_ident and a.icao = '[icao]'} (high low length) (<> tr (<> td high) (<> td low) (<> td length)))))) { If you wanted a cascade of transformations and were willing to use scheme s-expressions as an intermediate representation, this would even be simpler. } (define (runwayData icao) `(airport (icao ,icao) ,@(mapQuery (dbConnection) {select r.high_ident, r.low_ident, r.length from runway r, airport a where r.arpt_ident = a.arpt_ident and a.icao = '[icao]'} (high low length) (runway (highend ,high) (lowend ,low) (length ,length))))) |