source.mvb: Read R code and data from a file or connection

Description Usage Arguments Details Value Limitations Note See Also Examples

Description

source.mvb works like source(local=TRUE), except you can intersperse free-format data into your code. current.source returns the connection that's currently being read by source.mvb, so you can redirect input accordingly. To do this conveniently inside read.table, you can use from.here to read the next lines as data rather than R code.

Usage

1
2
3
4
5
6
7
source.mvb( con, envir=parent.frame(), max.n.expr=Inf,
  echo=getOption( 'verbose'), print.eval=echo,
  prompt.echo=getOption( 'prompt'), continue.echo=getOption( 'continue'))
current.source()
from.here( EOF=as.character(NA)) # Don't use it like this!
# Use "from.here" only inside "read.table", like so:
# read.table( file=from.here( EOF=), ...)

Arguments

con

a filename or connection

envir

an environment to evaluate the code in; by default, the environment of the caller of source

max.n.expr

finish after evaluating max.n.expr complete expressions, unless file ends first.

EOF

line which terminates data block; lines afterwards will again be treated as R statements.

...

other args to read.table

echo, print.eval, prompt.echo, continue.echo

as per source

Details

Calls to source.mvb can be nested, because the function maintains a stack of connections currently being read by source.mvb. The stack is stored in the list source.list in the mvb.session.info environment, on the search path. current.source returns the last (most recent) entry of source.list.

The sequence of operations differs from vanilla source, which parses the entire file and then executes each expression in turn; that's why it can't cope with interspersed data. Instead, source.mvb parses one statement, then executes it, then parses the next, then executes that, etc. Thus, if you include in your file a call to e.g.

text.line <- readLines( con=current.source(), n=1)

then the next line in the file will be read in to text.line, and execution will continue at the following line. readLines.mvb can be used to read text whose length is not known in advance, until a terminating string is encountered; lines after the terminator, if any, will again be evaluated as R expressions by source.mvb.

After max.n.expr statements (i.e. syntactically complete R expressions) have been executed, source.mvb will return.

If the connection was open when source.mvb is called, it is left open; otherwise, it is closed.

If you want to use read.table or scan etc. inside a source.mvb file, to read either a known number of lines or the rest of the file as data, you can use e.g. read.table( current.source(), ...).

If you want to read.table to read an unknown number of lines until a terminator, you could explicitly use readLines.mvb, as shown in the demo "source.mvb.demo.R". However, the process is cumbersome because you have to explicitly open and close a textConnection. Instead, you can just use read.table( from.here( EOF=...), ...) with a non-default EOF, as in Usage and the same demo (but see Note). from.here shouldn't be used inside scan, however, because a temporary file will be left over.

current.source() can also be used inside a source file, to work out the source file's name. Of course, this will only work if the file is being handled by source.mvb rather than source.

If you type source.list at the R command prompt, you should always see an empty list, because all source.mvb calls should have finished. However, the source list can occasionally become corrupt, i.e. containing invalid connections (I have only had this happen when debugging source.mvb and quitting before the exit code can clean up). If so, you'll get an error message on typing source.list (?an R bug?). Normally this won't matter at all. If it bothers you, try source.list <<- list().

Value

source.mvb returns the value of the last expression executed, but is mainly called for its side-effects of evaluating the code. from.here returns a connection, of class c( "selfdeleting.file", "file", "connection"); see Details. current.source returns a connection.

Limitations

Because source.mvb relies on pushBack, con=stdin() won't work.

Note

from.here creates a temporary file, which should be automatically deleted when read.table finishes (with or without an error). Technically, the connection returned by from.here is of class selfdeleting.file inheriting from file; this class has a specific close method, which unlinks the description field of the connection. This trick works inside read.table, which calls close explicitly, but not in scan or closeAllConnections, which ignore the selfdeleting.file class.

from.here() without an explicit terminator is equivalent to readLines( current.source()), and the latter avoids temporary files.

See Also

source, readLines.mvb, flatdoc, the demo in "source.mvb.demo.R"

Examples

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# You wouldn"t normally do it like this:
tt <- tempfile()
cat( "data <- scan( current.source(), what=list( x=0, y=0))",
"27 3",
"35 5",
file=tt, sep="\n")
source.mvb( tt)
unlink( tt)
data # list( x=c( 27, 35), y=c(3, 5))
# "current.source", useful for hacking:
tt <- tempfile()
cat( "cat( \"This code is being read from file\",",
"summary( current.source())$description)", file=tt)
source.mvb( tt)
cat( "\nTo prove the point:\n")
cat( scan( tt, what="", sep="\n"), sep="\n")
unlink( tt)

Example output

Loading required package: tools

Attaching package: 'mvbutils'

The following object is masked from 'package:graphics':

    clip

The following objects are masked from 'package:utils':

    ?, help

The following objects are masked from 'package:base':

    print.default, print.function, rbind, rbind.data.frame

Read 2 records
$x
[1] 27 35

$y
[1] 3 5

$x
[1] 27 35

$y
[1] 3 5

This code is being read from file /work/tmp/tmp/RtmpHctP6R/file38f6a6fa382NULL
Warning message:
In readLines(con) :
  incomplete final line found on '/work/tmp/tmp/RtmpHctP6R/file38f6a6fa382'

To prove the point:
Read 1 item
cat( "This code is being read from file", summary( current.source())$description)

mvbutils documentation built on May 2, 2019, 8:32 a.m.