On Mon, 6 Jul 2009, Riccardo (Jack) Lucchetti wrote:
On Mon, 6 Jul 2009, Allin Cottrell wrote:
> I've committed a few more changes to the gretl Rlib code. You can
> now (if you're set up right) call native R functions directly, as
> in
>
> <gretlscript>
> scalar c = choose(10,4)
> </gretlscript>
>
> That is, "choose" is recognized as an R function and (thanks to
> Christoph) is called via libR.
>
> At present this works only if the function arguments and return
> value are either scalars or matrices. That could be extended
> somewhat if we find this valuable.
Wow! This is absolutely fantastic! However, this is big, very
big. I have the feeling that we need to think this over very
carefully, for at least two reasons:
Yes, agreed on both counts.
(a) what happens in case of a name clash? ...
Yes, indeed. I've been thinking about that too. The first point
to make is that trying to interpret a "word" as an R function name
is the "last resort" in genlex.c. So any built-in, or
user-defined, gretl function will mask an R function of the same
name.
Perhaps we may wrap R function calls in an ad-hoc function, like
<gretlscript>
scalar c = R("choose(10,4)")
</gretlscript>
My first thought on this is to the same effect but a little
simpler: we could mark off R functions (either built-in, or
defined via "foreign" blocks within gretl) by using the prefix
"R_". So if you wanted to invoke the R "choose" function you'd
have to invoke it as "R_choose(args)". (Internally, we'd see the
"R_" and pass the remainder of the word to the new function
get_R_function_by_name().)
This would reliably avert clashes with gretl built-in functions
since gretl uses lower-case identifiers exclusively -- and I don't
envisage changing that since I hate mixed-case function names!
It does mean that if someone defines a user function "R_foo" it
will mask any "foo" function that may exist in R, but that doesn't
seems like a big problem to me -- particularly if the manual
mentions this point.
(b) are there portability problems?
Yes, it does raise a portability issue. We do have some of those
already: for example, the gretl command "mpols" will work only if
gretl is linked against (the optional) libgmp. There's also the
business of the optional third-party programs TRAMO/SEATS and
X-12-ARIMA. At present the functionality of these programs is
available only via the GUI, but it probably should be available
via script.
There are some other issues too.
libR is not an "ordinary" library: by plugging into its API you
basically "buy into" an R session. And this can be quite lumpy.
R seems to make liberal use of the evil "longjmp" function (C's
non-local goto -- and you thought that "goto" was bad!). So, for
example, the innocuous-looking R function "findFun" crashes the
caller on failure. Similarly, a call to "Rf_initEmbeddedR" will
abort the caller if the environment is not set up correctly for R.
I've tried to guard against both of these issues in recent changes
in gretl_foreign.c, but I'm sure there are more.
In addition, if you run a gretl/Rlib session under valgrind
valgrind --tool=memcheck --leak-check=full --show-reachable=yes
you'll see that libR wants to allocate at least 10 MB before it
does _anything_. Christoph gave an example function, defined in
R, that took a scalar argument and returned its argument plus 1.
Fine, R will do that for you if you give it 10 MB of RAM and a
several dozen function calls. (OK, any library uses resources;
I'm just saying that the libR approach is not a magic bullet for
saving on initialization costs.)
Allin.