RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Using Gambit-C Scheme to Create Small, Efficient Native Applications : Page 5

When you need to build small, native standalone applications, Gambit-C Scheme provides a high-level dynamic language with good runtime and memory performance, as well as good deployment options.


Implementing a Web Service as a Standalone Executable

Using the function find-human-names from the previous section, you can implement a web service that returns a list of names when called with input text. First, you will need a web server. Marc Feeley (the author of Gambit-C) includes a web server example with the source code distribution of Gambit-C. The web server in this section is a simpler version (implemented in about 50 lines of Scheme code) that Marc posted on the comp.lang.scheme newsgroup. Adding calls to the name finder code and displaying an HTML input form requires only a few lines of extra code. The web server implementation is in the file web.scm, which is mostly Marc Feeley's code with the following added snippets:
   (define (http-get connection document)
    (print port: connection
           "HTTP/1.0 200 OK\n"
           "Content-Type: text/html; charset=ISO-8859-1\n"
           "Connection: close\n"
             (<h3> "Enter text that contains peoples names")
              "<input type=\"text\" name=\"text\" size=\"80\" /><br/>"
              "<input type=\"submit\" />")
              "Names in text:\n"
              (map (lambda (str) (list str "\n"))
                   (find-human-names (list->vector (string-tokenize document)))))))))

   (define (<html> . body) (list "<html>" body "</html>"))
   (define (<body> . body) (list "<body>" body "</body>"))
   (define (<h3> . body) (list "<h3>" body "</h3>"))
   (define (<pre> . body) (list "<pre>" body "</pre>"))
   (define (<form> . body) (list "<form>" body "</form>"))

The function http-get is called whenever a new HTTP GET request is received. The input argument document is a string that is the URL-encoded request. I use the function string-tokenize (defined in the file proper-names.scm) to split up the request. This is not a complete or proper way to URL decode data, but it works for this example. The function string-tokenize returns a list of strings, so I use Scheme's list->vector function to convert the list to a vector. I then call the function find-human-names, which is defined in the file proper-names.scm.

You can run the web app using this code and access it using the URL http://localhost:8000:

> (load "people-data-tables.scm")
"/Volumes/Data/ideas/DevX/Gambit-C apps/code/name-finder/people-data-tables.scm"
> (load "proper-names.scm")
"/Volumes/Data/ideas/DevX/Gambit-C apps/code/name-finder/proper-names.scm"
> (load "web.scm")

The next section shows the makefile you need to create standalone, self-contained executables for both a command-line name finder tool and the web application.

Makefile for Building the Command Line and Web Application Examples

The source code for both the command-line name finder tool and web application examples is located in the directory name-finder. You can use the following makefile to build the examples:
   rm -f *~
   rm -f */*~
   rm -f \#*
   rm -f */\#*
   rm -f *.c
   rm -f out.txt
   rm -f web
   rm -f testapp

   gsc -exe proper-names.scm people-data-tables.scm testapp.scm

   gsc -exe proper-names.scm people-data-tables.scm web.scm

The following listing shows the build process and running both examples (command lines in bold font):

markw$ make app webapp
gsc -exe proper-names.scm people-data-tables.scm testapp.scm
/Volumes/Data/ideas/DevX/Gambit-C apps/code/name-finder/proper-names.c:
/Volumes/Data/ideas/DevX/Gambit-C apps/code/name-finder/people-data-tables.c:
/Volumes/Data/ideas/DevX/Gambit-C apps/code/name-finder/testapp.c:
/Volumes/Data/ideas/DevX/Gambit-C apps/code/name-finder/testapp_.c:
gsc -exe proper-names.scm people-data-tables.scm web.scm
/Volumes/Data/ideas/DevX/Gambit-C apps/code/name-finder/proper-names.c:
/Volumes/Data/ideas/DevX/Gambit-C apps/code/name-finder/people-data-tables.c:
/Volumes/Data/ideas/DevX/Gambit-C apps/code/name-finder/web.c:
/Volumes/Data/ideas/DevX/Gambit-C apps/code/name-finder/web_.c:
markws-macbook:name-finder markw$ ./testapp -i test.txt -o out.txt
markws-macbook:name-finder markw$ cat out.txt 
President Obama
President Clinton
markws-macbook:name-finder markw$ ./web  ; start the web service

You can easily modify this example to act as a REST-style web service as well.

So, what would be a good use of small, self-contained executables for a web application and/or REST-style web service? A very good use case would be writing applications that run in a user's web browser but with a local server. If you implement a "locally hosted" application using Ruby on Rails or server-side Java, for example, the end user or your program has to install multiple files on the system. The resulting web application will take up more memory and run slower than a Gambit-C application. I have benchmarked simple Gambit-C web apps that run with HTTP response times about 4 or 5 times less than a Rails app with the same functionality.

The Benefits of Gambit-C Scheme

I hope that you have enjoyed this quick introduction to Scheme and building standalone executable programs using Gambit-C. For research or experimental coding, the combination of Gambit-C Scheme with Emacs and Slime is one of my favorite development environments because of the fast and efficient style of interactive development it provides. As demonstrated here, a further benefit is the ability to package applications as small, efficient standalone applications.

In addition to writing command-line utilities, I am replacing Java code that I use to implement Hadoop Map/Reduce processes with Scheme versions that have better functionality. While the runtime performance of Java is very good, the higher level and more expressive nature of Scheme makes using Gambit-C Scheme a better choice for my project.

As a final note, Gambit-C Creator Marc Feeley does a great job of maintaining the language, and he also quickly answers questions posed on the Gambit mailing list and the comp.lang.scheme Google Group (or usenet group). He also made useful comments and corrections on a draft of this article and provided sample code.

Mark Watson is a Java consultant and the author of 14 books on Java, artificial intelligence, C++, and intelligent agents.
Email AuthorEmail Author
Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date