Skip to contents


library(saferDev)


Datasets

# Function with all the bodies delimited by curly brackets.
fun1 <- function(x){
    if(x > 1){
        base::return(x)
    }else{
        base::return(0)
    }
    for(i in 1:3){
        base::print(i)
    }
    while(x > 1){
        x <- x - 1
    }
    repeat{
        x <- x + 1
    }
    base::sapply(X = 1:3, FUN = function(y){
        y * 2
    })
}
# Function with some bodies not delimited by curly brackets.
fun2 <- function(x){
    if(x > 1)
        base::return(x)
    else
        base::return(0)
    for(i in 1:3)
        base::print(i)
    while(x > 1)
        x <- x - 1
    repeat
        x <- x + 1
    base::sapply(X = 1:3, FUN = function(y) y * 2)
}


Datasets info

fun1 # Function.
## function (x) 
## {
##     if (x > 1) {
##         base::return(x)
##     }
##     else {
##         base::return(0)
##     }
##     for (i in 1:3) {
##         base::print(i)
##     }
##     while (x > 1) {
##         x <- x - 1
##     }
##     repeat {
##         x <- x + 1
##     }
##     base::sapply(X = 1:3, FUN = function(y) {
##         y * 2
##     })
## }
fun2 # Function.
## function (x) 
## {
##     if (x > 1) 
##         base::return(x)
##     else base::return(0)
##     for (i in 1:3) base::print(i)
##     while (x > 1) x <- x - 1
##     repeat x <- x + 1
##     base::sapply(X = 1:3, FUN = function(y) y * 2)
## }


Argument x

# Test if all the bodies of fun1 are delimited by curly brackets.
# Here everything is fine.
curly_bracket_check(x = fun1)
## 
## 
## AFTER RUNNING saferDev::curly_bracket_check().
## INSIDE fun1(), EVERYTHING SEEMS CLEAN.
# Here some bodies are not delimited by curly brackets.
curly_bracket_check(x = fun2)
## 
## 
## 
## INSIDE fun2(), SOME CURLY BRACKETS {} ARE MISSING AFTER:
## 
## LINE CONSTRUCT       CODE
## 3    if      if (x > 1) 
## 5    else        else base::return(0)
## 6    for     for (i in 1:3) base::print(i)
## 7    while       while (x > 1) x <- x - 1
## 8    repeat      repeat x <- x + 1
## 9    function        base::sapply(X = 1:3, FUN = function(y) y * 2)
## function (x) 
## {
##     if (x > 1) {
##         base::return(x)
##     }
##     else {
##         base::return(0)
##     }
##     for (i in 1:3) {
##         base::print(i)
##     }
##     while (x > 1) {
##         x <- x - 1
##     }
##     repeat {
##         x <- x + 1
##     }
##     base::sapply(X = 1:3, FUN = function(y) {
##         y * 2
##     })
## }


Argument safer_check

# Safer checkings are performed before main code running.
curly_bracket_check(
    x = fun1, 
    safer_check = TRUE
)
## 
## 
## AFTER RUNNING saferDev::curly_bracket_check().
## INSIDE fun1(), EVERYTHING SEEMS CLEAN.


Argument lib_path

# The "NOTGOOD" path does not exists.
curly_bracket_check(
    x = fun1,  
    lib_path = "NOTGOOD"
)
## Error:
## ! 
## 
## ================
## 
## ERROR IN saferDev::curly_bracket_check().
## 
## THE DIRECTORY PATH INDICATED IN THE lib_path ARGUMENT DOES NOT EXIST:
## NOTGOOD
## 
## ================


Argument error_text

# Add a text in error messages returned by curly_bracket_check().
curly_bracket_check(
    x = fun1, 
    lib_path = "NOTGOOD", 
    error_text = " === TEXT ADDED ==="
)
## Error:
## ! 
## 
## ================
## 
## ERROR IN saferDev::curly_bracket_check() === TEXT ADDED ===
## 
## THE DIRECTORY PATH INDICATED IN THE lib_path ARGUMENT DOES NOT EXIST:
## NOTGOOD
## 
## ================


Arguments export and out_path: return or export the corrected function

# The corrected function is returned (NULL if nothing has to be corrected).
fun2_safer <- curly_bracket_check(x = fun2)
## 
## 
## 
## INSIDE fun2(), SOME CURLY BRACKETS {} ARE MISSING AFTER:
## 
## LINE CONSTRUCT       CODE
## 3    if      if (x > 1) 
## 5    else        else base::return(0)
## 6    for     for (i in 1:3) base::print(i)
## 7    while       while (x > 1) x <- x - 1
## 8    repeat      repeat x <- x + 1
## 9    function        base::sapply(X = 1:3, FUN = function(y) y * 2)
fun2_safer # { } added around each reported body.
## function (x) 
## {
##     if (x > 1) {
##         base::return(x)
##     }
##     else {
##         base::return(0)
##     }
##     for (i in 1:3) {
##         base::print(i)
##     }
##     while (x > 1) {
##         x <- x - 1
##     }
##     repeat {
##         x <- x + 1
##     }
##     base::sapply(X = 1:3, FUN = function(y) {
##         y * 2
##     })
## }
# The corrected function behaves like the submitted one.
fun2(1)
## [1] 0
fun2_safer(1)
## [1] 0
# And it passes the check.
curly_bracket_check(x = fun2_safer)
## 
## 
## AFTER RUNNING saferDev::curly_bracket_check().
## INSIDE fun2_safer(), EVERYTHING SEEMS CLEAN.
# Export the corrected function into the fun2_safer.R file, here in a new temporary folder.
# out_path = "." (default) is the R working directory.
# An existing file is never overwritten (an error is returned instead).
tempo_dir <- base::tempfile(pattern = "dir", tmpdir = base::tempdir(), fileext = "")
base::dir.create(path = tempo_dir, showWarnings = TRUE, recursive = FALSE, mode = "0777")
curly_bracket_check(
    x = fun2,
    export = TRUE,
    out_path = tempo_dir
)
## 
## 
## 
## INSIDE fun2(), SOME CURLY BRACKETS {} ARE MISSING AFTER:
## 
## LINE CONSTRUCT       CODE
## 3    if      if (x > 1) 
## 5    else        else base::return(0)
## 6    for     for (i in 1:3) base::print(i)
## 7    while       while (x > 1) x <- x - 1
## 8    repeat      repeat x <- x + 1
## 9    function        base::sapply(X = 1:3, FUN = function(y) y * 2)
## MODIFIED CODE EXPORTED IN:
## /tmp/RtmpKZFTh1/dir178451064049/fun2_safer.R
# base::source() of this file recreates the corrected function, named fun2_safer.
base::readLines(con = base::file.path(tempo_dir, "fun2_safer.R", fsep = "/"))
##  [1] "fun2_safer <- function (x) "                  
##  [2] "{"                                            
##  [3] "    if (x > 1) {"                             
##  [4] "        base::return(x)"                      
##  [5] "    }"                                        
##  [6] "    else {"                                   
##  [7] "        base::return(0)"                      
##  [8] "    }"                                        
##  [9] "    for (i in 1:3) {"                         
## [10] "        base::print(i)"                       
## [11] "    }"                                        
## [12] "    while (x > 1) {"                          
## [13] "        x <- x - 1"                           
## [14] "    }"                                        
## [15] "    repeat {"                                 
## [16] "        x <- x + 1"                           
## [17] "    }"                                        
## [18] "    base::sapply(X = 1:3, FUN = function(y) {"
## [19] "        y * 2"                                
## [20] "    })"                                       
## [21] "}"


All the arguments

curly_bracket_check(
    x = fun1, # function name to test.
    export = FALSE, # write the corrected function into a .R file instead of returning it?
    out_path = ".", # folder where to write the file (used only if export = TRUE).
    safer_check = TRUE, # perform some "safer" checks (see https://github.com/safer-r)?
    lib_path = NULL, # where the required packages are if not in the default directories.
    error_text = "" # add information in error messages returned by the function.
)
## 
## 
## AFTER RUNNING saferDev::curly_bracket_check().
## INSIDE fun1(), EVERYTHING SEEMS CLEAN.


Sophisticated example

# The body of a primitive function cannot have curly brackets: skipped.
curly_bracket_check(x = base::`+`)
## 
## 
## AFTER RUNNING saferDev::curly_bracket_check().
## INSIDE base::`+`(), EVERYTHING SEEMS CLEAN.
# The body of base::mean() is UseMethod("mean"): reported.
curly_bracket_check(x = base::mean)
## 
## 
## 
## INSIDE base::mean(), SOME CURLY BRACKETS {} ARE MISSING AFTER:
## 
## LINE CONSTRUCT       CODE
## 1    function        function (x, ...)
## function (x, ...) 
## {
##     UseMethod("mean")
## }
## <environment: namespace:base>