Skip to contents


library(saferDev)


Datasets

# Warning: the \(x) lambda writing is only kept in the code of a function carrying its source references (srcref). The functions are therefore built with base::parse(keep.source = TRUE) followed by base::eval(), whatever the value of base::getOption("keep.source").
# Function with all the anonymous functions written with the standard function() writing.
fun1 <- eval(parse(text = "function(x){ base::sapply(X = 1:3, FUN = function(y){ y * 2 }) }", keep.source = TRUE))
# Function with some anonymous functions written with the lambda writing \\().
fun2 <- eval(parse(text = "function(x){ base::sapply(X = 1:3, FUN = \\(y){ y * 2 }) ; base::lapply(X = x, FUN = \\(z) z + 1) }", keep.source = TRUE))


Datasets info

fun1 # Function.
## function(x){ base::sapply(X = 1:3, FUN = function(y){ y * 2 }) }
fun2 # Function.
## function(x){ base::sapply(X = 1:3, FUN = \(y){ y * 2 }) ; base::lapply(X = x, FUN = \(z) z + 1) }


Argument x

# Test if all the anonymous functions of fun1 are written with the standard function() writing.
# Here everything is fine.
lambda_check(x = fun1)
## 
## 
## AFTER RUNNING saferDev::lambda_check().
## INSIDE fun1(), EVERYTHING SEEMS CLEAN.
## NULL
# Here some anonymous functions are written with the lambda writing.
lambda_check(x = fun2)
## 
## 
## 
## INSIDE fun2(), SOME LAMBDA FUNCTIONS ARE NOT WRITTEN function():
## 
## LINE SYMBOL      CODE
## 1    \(y)        function(x){ base::sapply(X = 1:3, FUN = \(y){ y * 2 }) ; base::lapply(X = x, FUN = \(z) z + 1) }
## 1    \(z)        function(x){ base::sapply(X = 1:3, FUN = \(y){ y * 2 }) ; base::lapply(X = x, FUN = \(z) z + 1) }
## 
## MODIFIED FUNCTION RETURNED BY return().
## function (x) 
## {
##     base::sapply(X = 1:3, FUN = function(y) {
##         y * 2
##     })
##     base::lapply(X = x, FUN = function(z) z + 1)
## }


Argument safer_check

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


Argument lib_path

# The "NOTGOOD" path does not exists.
lambda_check(
    x = fun1,  
    lib_path = "NOTGOOD"
)
## Error:
## ! 
## 
## ================
## 
## ERROR IN saferDev::lambda_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 lambda_check().
lambda_check(
    x = fun1, 
    lib_path = "NOTGOOD", 
    error_text = " === TEXT ADDED ==="
)
## Error:
## ! 
## 
## ================
## 
## ERROR IN saferDev::lambda_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 <- lambda_check(x = fun2)
## 
## 
## 
## INSIDE fun2(), SOME LAMBDA FUNCTIONS ARE NOT WRITTEN function():
## 
## LINE SYMBOL      CODE
## 1    \(y)        function(x){ base::sapply(X = 1:3, FUN = \(y){ y * 2 }) ; base::lapply(X = x, FUN = \(z) z + 1) }
## 1    \(z)        function(x){ base::sapply(X = 1:3, FUN = \(y){ y * 2 }) ; base::lapply(X = x, FUN = \(z) z + 1) }
## 
## MODIFIED FUNCTION RETURNED BY return().
fun2_safer # \\() replaced by function().
## function (x) 
## {
##     base::sapply(X = 1:3, FUN = function(y) {
##         y * 2
##     })
##     base::lapply(X = x, FUN = function(z) z + 1)
## }
# The corrected function behaves like the submitted one.
fun2(1)
## [[1]]
## [1] 2
fun2_safer(1)
## [[1]]
## [1] 2
# And it passes the check.
lambda_check(x = fun2_safer)
## 
## 
## AFTER RUNNING saferDev::lambda_check().
## INSIDE fun2_safer(), EVERYTHING SEEMS CLEAN.
## NULL
# 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")
lambda_check(
    x = fun2,
    export = TRUE,
    out_path = tempo_dir
)
## 
## 
## 
## INSIDE fun2(), SOME LAMBDA FUNCTIONS ARE NOT WRITTEN function():
## 
## LINE SYMBOL      CODE
## 1    \(y)        function(x){ base::sapply(X = 1:3, FUN = \(y){ y * 2 }) ; base::lapply(X = x, FUN = \(z) z + 1) }
## 1    \(z)        function(x){ base::sapply(X = 1:3, FUN = \(y){ y * 2 }) ; base::lapply(X = x, FUN = \(z) z + 1) }
## MODIFIED CODE EXPORTED IN:
## /tmp/Rtmp1OQqlM/dir19287d15a419/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){ base::sapply(X = 1:3, FUN = function(y){ y * 2 }) ; base::lapply(X = x, FUN = function(z) z + 1) }"


All the arguments

lambda_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::lambda_check().
## INSIDE fun1(), EVERYTHING SEEMS CLEAN.
## NULL


Sophisticated example

# A lambda written in a string or in a comment is ignored.
fun3 <- eval(parse(text = "function(x){ if(x > 1){ y <- \"the \\(x) writing in a string\" } ; x }", keep.source = TRUE))
## Error:
## ! '\(' is an unrecognized escape in character string (<text>:1:36)
lambda_check(x = fun3)
## Error:
## ! object 'fun3' not found
# The backquoted `\\` call (the deprecated function() writing) is not a lambda writing: ignored.
fun4 <- eval(parse(text = "function(x){ base::`\\\\`(x) }", keep.source = TRUE))
lambda_check(x = fun4)
## 
## 
## AFTER RUNNING saferDev::lambda_check().
## INSIDE fun4(), EVERYTHING SEEMS CLEAN.
## NULL