My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
ExtendingRFortran  
Explains how to extend the functionality of RFortran
Updated Jun 3, 2009 by mark.th...@gmail.com

Rationale for custom functions

If you have used RFortran a while you will notice that only the basics have been implemented and that there are certain combinations of commands you may use with high frequency. The best practice is to combine the often repeated command sequences into a function, for example: Rput('x',x),Rput('y',y),Rput('plot(x,y)') could be put into a single function such as this:

function Rplot(x,y) result(ok)
 implicit none
 real, intent(in) :: x(:) ! input x-axis data
 real, intent(in) :: y(:) ! input y-axis data
 logical :: ok            ! error flag
        
 ok = Rput('x',x)
 ok = Rput('y',y)
 ok = Rput('plot(x,y)')
end function

Where to include custom functions

As R is becoming larger by the minute, it is not possible for us to anticipate all of the ways in which a user would use RFortran. If you have extensions to RFortran they can be included in any of the files 'Rfortran_Rfuncs.f90', 'Rfortran_Robjects.f90', 'Rfortran_Rplots.f90'. The above example would be appropriate for the Rplots file. The Robjects file will be discussed in the next section, and all other routines should go into Rfuncs.

Custom Objects

A common scenario is when R produces some kind of object that has multiple parts. Using the base-functionality the only way to transfer them is to use multiple commands on the individual parts. Consider for example an object called 'ks' which is the result from a Kolmogrov-Smirnov test using R: 'ks<-ks.test(x,y)'. The resultant object has several components and to transfer it back to Fortran we would need to transfer each part separately. If this is an object you commonly use, then why not create a corresponding data object in Fortran and a function to transfer this object? An example is given below (note that the same naming convention of the objects between R and Fortran has been maintained and where R uses a period in the variable name, an undersocre has been used in Fortran):

module custom
  type ks_type ! definition of an object that matches the ks object within R
    real :: statistic
    real :: p_value
    character(len = 32) :: alternative
    character(len = 32) :: method
    character(len = 32) :: data_name
  end type

  contains
  function Rget_ks(var,ks) result(ok)
    implicit none
    character(*), intent(in)  :: var    ! R variable name/symbol
    type(ks_type), intent(inout) :: ks  ! object as defined above
    integer  :: ok                      ! error flag

    ok = Rget(var//"$statistic",  ks%statistic)
    ok = Rget(var//"$p.value",    ks%p_value)
    ok = Rget(var//"$alternative",ks%alternative)
    ok = Rget(var//"$method",     ks%method)
    ok = Rget(var//"$data.name",  ks%data_name)
  end function 
end module

Style guide

We have tried to keep a convention of using the letter 'R' at the start of the function name if the routine interacts with R or if it is a wrapper for an R function of the same name. This helps avoid potential collisions amongst routines with common names such as 'plot' and also makes it clear which routines in your code are those that depend upon R. We have implemented the functions so that they return a single integer value as an error code (0 is good, anything else is bad). Please stick to the structure: 'ok = Rrandomfunc()' where ok is the variable name to store the returned error code. If you make several calls inside a function, you should check all of the error flags to see if they were okay, otherwise if the last one is okay (but others failed) it will give the appearance that the whole function was successful. This mechanism does not provide an error message, but you can use the message_log facilities to output messages. If there are numerous R commands that belong together, it is highly recommended that the the commands are stored as separate R-scripts and that RFortran is merely used for putting/getting data into/from R. The reasoning behind this comes from experience: if your code looks like this:

ok = Rput('command1')
ok = Rput('command2')
ok = Rput('command3')
ok = Rput('command4')

then it is harder to debug than if they were stored as a script. Secondly, if they are stored as an Rscript it is possible to change the script without needing to recompile the program. If there are commonly used tools then these can be preloaded into R via the RFortran_scriptpathIn argument when Rinit() is called. Otherwise if it is program specific it could be stored elsewhere and called via Rput('source(MySpecialScript.R)').


Sign in to add a comment
Powered by Google Project Hosting