Blame | Last modification | View Log | Download | RSS feed
<?xml version="1.0"?><!DOCTYPE literate SYSTEM "literate.dtd" [<!ENTITY % forS "INCLUDE"><!ENTITY % forR "IGNORE">]><literate><doc>This document is a very early attempt to illustrate how we might useXML for "literate programming" with the S language. The idea is thatwe write code to be read by ahuman rather than the machine, but thatin the process, we also generate the code. The goal is to developmore readable, understandable and hence maintainable and useful code.The topic was pionereed by Donald Knuth and there are variouspieces of software that do it in different format. XML isa rather natural form. See also<a href="http://www.oasis-open.org/cover/xmlLitProg.html">Oasis-open</a><P />There are numerous practical benefits associated with using literateprogramming techniques. For one, it is easy to comment out code whilestill leaving it in the source. It is also easy to have two pieces ofsimilar code and swap them when experimenting with some modifications.Also, it is easy to reuse a block of code without having to playpre-processor tricks.<P/>In this example, we are going to mix programming languages within thesame file. We will write an S-language (meaning both SPlus and R andfrom here on, simply referred to as S) function which calls a Croutine to perform the computation. The function is uninteresting andsimply computes the process identifier of the R session.It calls the C function <croutine>getpid</croutine>to do this.</doc><function language="R"><doc>The function takes no arguments and returnsa numeric vector of length 1.</doc><![CDATA[getpid <-function() {.Call("RS_getpid")}]]></function><code language="C"><a href="includes" /><a href="RS_getpid" /></code><doc>The <croutine>getpid</croutine>is declared in the <file>unistd.h</file>header file. So we include it here.</doc><code name="includes"><![CDATA[#include <unistd.h>]]></code><code name="includes"><![CDATA[#include <Rinternals.h>]]></code><code language="C">USER_OBJECT_RS_getpid(){USER_OBEJCT_ ans;pid_t id;id = getpid();NEW_NUMERIC(1);NUMERIC_DATA(ans)[0] = id;return(id);}</code><function language="R"><doc>This is gratuitous text.</doc>while(T) {<a href="iterate" />}</function><doc>Note how we use the <b>sgets</b> entity here to avoid having to use aCDATA construct to escape the text.</doc><code id="iterate">if(x > 10)breakelsex %sgets; rnorm(9)</code><doc>What we are trying to do here is produce elementsthat are processed conditionally.It appears that INCLUDE andIGNORE directives have to be within DTDs. (Is this true?)Hence we escape them here.</doc><code><![CDATA[<![ %forS [x = y@slot] ]><![ %forR [x <- y$slot] ]>]]></code></literate>