diff --git a/README.md b/README.md index ea15132cde7b17deb8c378be9f9414eec350641c..2a347a867c8433e6ef2b3569ce1dff2c777b2bb3 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,11 @@ Source the cute_little_functions.R into R/RStudio to have the functions availabl WHAT'S NEW IN +v1.4: + +1) Debugged + + v1.3: 1) NULL arguments, non NULL argument, logical and NA arguments added @@ -12,4 +17,4 @@ v1.3: v1.2: -1) printing result improvement +1) Printing result improvement diff --git a/r_debugging_tools.R b/r_debugging_tools.R index 7489584496fd6fad7ae079a0e779283e83dcc4ff..f9dd03d096784a88b7add331cf79e39a763fff20 100644 --- a/r_debugging_tools.R +++ b/r_debugging_tools.R @@ -1,10 +1,10 @@ ################################################################ ## ## -## R DEBUGGING TOOLS v1.2 ## +## R DEBUGGING TOOLS v1.4 ## ## ## ## Gael A. Millot ## ## ## -## Compatible with R v3.5.1 ## +## Compatible with R v4.0.2 ## ## ## ################################################################ @@ -19,47 +19,68 @@ str_basic_arg_check_dev <- ' # STRING function.name <- as.list(match.call(expand.dots=FALSE))[[1]] default.arg.list <- formals(fun = sys.function(sys.parent(n = 2))) # list of all the arguments of the function with their default values (not the values of the user !). Use n = 2 when he string has to be evaluated by eval() inside a function. Use n=1 (default) if not evaluation. It seems that ls() as first line of the function provide the names of the arguments (empty, called, etc., or not) -arg.without.default.value <- sapply(default.arg.list, is.symbol) & sapply(sapply(default.arg.list, as.character), identical, "") # logical to detect argument without default values (these are typeof "symbol" and class "name" and empty character +arg.without.default.value.log <- sapply(default.arg.list, is.symbol) & sapply(sapply(default.arg.list, as.character), identical, "") # logical indicating argument without default values (these are typeof "symbol" and class "name" and empty character name.or.empty.default.val.arg.log <- sapply(default.arg.list, FUN = "class") == "name" -if(length(name.or.empty.default.val.arg.log) != length(arg.without.default.value)){ -stop(paste0("\n\n================\n\nINTERNAL ERROR IN str_basic_arg_check_dev IN ", function.name,". CODE MUST BE MODIFED\n\n================\n\n")) -}else if(any(name.or.empty.default.val.arg.log & ! arg.without.default.value)){ -cat(paste0("\n\n================\n\nALERT\nDEFAULT VALUE OF ARGUMENT OF ", function.name," MUST NOT BE A VARIABLE (POTENTIAL PROBLEM OF SCOPE)\nTHE CONCERNED ARGUMENTS ARE:\n", paste(names(formals(fun = sys.function(sys.parent(n = 2))))[name.or.empty.default.val.arg.log & ! arg.without.default.value], collapse = "\n"), "\n\n================\n\n")) +if(length(name.or.empty.default.val.arg.log) != length(arg.without.default.value.log)){ + stop(paste0("\n\n================\n\nINTERNAL ERROR IN str_basic_arg_check_dev IN ", function.name,". CODE MUST BE MODIFED\n\n================\n\n")) +}else if(any(name.or.empty.default.val.arg.log & ! arg.without.default.value.log)){ + cat(paste0("\n\n================\n\nALERT\nDEFAULT VALUE OF ARGUMENT OF ", function.name," MUST NOT BE A VARIABLE (POTENTIAL PROBLEM OF SCOPE)\nTHE CONCERNED ARGUMENTS ARE:\n", paste(names(formals(fun = sys.function(sys.parent(n = 2))))[name.or.empty.default.val.arg.log & ! arg.without.default.value.log], collapse = "\n"), "\n\n================\n\n")) +} + +if(any(arg.without.default.value.log)){ + arg.without.default.value <- default.arg.list[arg.without.default.value.log] +}else{ + arg.without.default.value <- NULL +} +if(any( ! arg.without.default.value.log)){ + arg.with.default.value <- default.arg.list[ ! arg.without.default.value.log] +}else{ + arg.with.default.value <- NULL } cat(paste0("\n\n================================\n\n", function.name," FUNCTION ARGUMENT CHECKING\n\n================================\n")) cat(paste0("\n================\nARGUMENTS OF THE FUNCTION ARE (INCLUDING DEFAULT VALUES):\n\n")) print(default.arg.list) -if(any(arg.without.default.value)){ # argument names that are empty by default added now because null arguments will not be inserted thenafter -cat(paste0("\n================\nARGUMENTS WITHOUT DEFAULT VALUES ARE: ", paste(names(default.arg.list)[arg.without.default.value], collapse= " "))) +if(any(arg.without.default.value.log)){ # argument names that are empty by default added now because null arguments will not be inserted thenafter + cat(paste0("\n================\nARGUMENTS WITHOUT DEFAULT VALUES ARE:\n", paste(names(arg.without.default.value)[arg.without.default.value.log], collapse= "\n"))) }else{ -cat(paste0("\n================\nNO ARGUMENTS WITHOUT DEFAULT VALUES")) + cat(paste0("\n================\nNO ARGUMENTS WITHOUT DEFAULT VALUES")) } -if(any(sapply(default.arg.list, FUN = is.null))){ -cat(paste0("\n================\nNULL ARGUMENTS ARE: ", paste(names(default.arg.list)[sapply(default.arg.list, FUN = is.null)], collapse= " "))) +if(any( ! arg.without.default.value.log)){ + if(any(sapply(arg.with.default.value, FUN = is.null))){ + cat(paste0("\n================\nNULL ARGUMENTS ARE:\n", paste(names(arg.with.default.value)[sapply(arg.with.default.value, FUN = is.null)], collapse= "\n"))) + } }else{ -cat(paste0("\n================\nNO NULL ARGUMENTS")) + cat(paste0("\n================\nNO NULL ARGUMENTS")) } - -if(any( ! sapply(default.arg.list, FUN = is.null))){ -cat(paste0("\n================\nNON NULL ARGUMENTS ARE: ", paste(names(default.arg.list)[ ! sapply(default.arg.list, FUN = is.null)], collapse= " "))) +tempo.na <- NULL +if(any( ! arg.without.default.value.log)){ + if(any( ! sapply(arg.with.default.value, FUN = is.null))){ + cat(paste0("\n================\nNON NULL ARGUMENTS ARE:\n", paste(names(arg.with.default.value)[ ! sapply(arg.with.default.value, FUN = is.null)], collapse= "\n"))) + tempo <- arg.with.default.value[ ! sapply(arg.with.default.value, FUN = is.null)] + if(any(sapply(tempo, FUN = is.na))){ + tempo.na <- paste0("\n================\nNA ARGUMENTS ARE:\n", paste(names(tempo)[sapply(tempo, FUN = is.na)], collapse= "\n")) + }else{ + tempo.na <- paste0("\n================\nNO NA ARGUMENTS") + } + } }else{ -cat(paste0("\n================\nNO NON NULL ARGUMENTS")) + cat(paste0("\n================\nNO NON NULL ARGUMENTS")) } -if(any(sapply(default.arg.list, FUN = is.logical))){ -cat(paste0("\n================\nLOGICAL ARGUMENTS ARE: ", paste(names(default.arg.list)[sapply(default.arg.list, FUN = is.logical)], collapse= " "))) +if(any( ! arg.without.default.value.log)){ + if(any(sapply(arg.with.default.value, FUN = is.logical))){ + cat(paste0("\n================\nLOGICAL ARGUMENTS ARE:\n", paste(names(arg.with.default.value)[sapply(arg.with.default.value, FUN = is.logical)], collapse= "\n"))) + } }else{ -cat(paste0("\n================\nNO LOGICAL ARGUMENTS")) + cat(paste0("\n================\nNO LOGICAL ARGUMENTS")) } -if(any(sapply(default.arg.list, FUN = is.na))){ -cat(paste0("\n================\nNA ARGUMENTS ARE: ", paste(names(default.arg.list)[sapply(default.arg.list, FUN = is.na)], collapse= " "))) -}else{ -cat(paste0("\n================\nNO NA ARGUMENTS")) +if(! is.null(tempo.na)){ + cat(tempo.na) } cat(paste0("\n================\n\n"))