Preformatted text@yannick
Hi Yannick and developer colleagues,
I would like to propose the following and discuss the idea.
**Problem to solve: ** Currently, server functions (especially assign functions) appear not to provide a suitable mechanism to indicate a successful or non-successful outcome of the server function execution. This situation has led to write some client functions that are challenging to maintain, due to an excessive amount of code. The latter is often written to verify some values have been assigned on the server.
Proposal: I would like to suggest that a status and error to be handled by datashield.assign and datashield.aggregate. A class name FunctionOutcome should be defined with three private variables; i.e., status, error and value. A public method sets the value of these three private variables. Some get methods give access to the private values.
Server functions should return instantiations of this class. Then datashield.assign function can remove the value in the object, before returning it to the analysis server. The datashield.aggregate function can leave the object as it is. Finally, Datashield.assign and datashield.aggregate should remain backward compliant to the current functions.
I have an example below. The function uses a tryCatch function to catch the warnings and errors thrown by the main helper function. This statement would provide some information why the server function has stopped its execution, without completely stopping the execution of the R program…
Example code: [Example code]
#’@title createMatrixRUnifDS creates a matrix of n rows and columns using a uniform distribution. Assign server function. #’@description This server function function randomly generates some numbers using a uniform distribution. The latter is then coerced into a matrix. #’@param no.rows a number of rows greater than 11. Set to 11 by default #’@param no.cols a number of columns greater than 13. Set to 13 by default #’@param min a numerical value that indicates the possible minimum value of the distribution. Set to largest double value by default #’@param max a numerical value that indicates the possible minimum value of the distribution. Set to largest double value by default #’@return a matrix of no.rows and no.columns. #’@details This function stops if the number of rows or the number of columns is too disclosive. For that reason, a minimum of rows has been set #'to 11. The minimum or columns is set to 13. When a suitable matrix size is passed, the minimum and maximum values are guaranteed to be in an appropriate order. #'For example, when the minimum value is greater than the maximum value, the error is corrected. A warning is then thrown. A uniform distribution is created using the R function importFrom(“stats”, “runif”). #‘The outcome is then coerced into matrix, using the parameters no.rows and no.columns. #’@author P.Ryser-Welch, Newcastle University, DataSHIELD team
FunctionOutcome <- R6Class(“FunctionOutcome”, public = list ( SUCCESS = 0, WARNING = 1, FAIL = 2, set = function(status,error, value) { private$status = status private$error = error private$value = value }, delete_value = function() private$value = NULL, get_status = function() return(private$status), get_error = function() return(private$error), get_value = function() return(value) ), private = list( status = -1, error = “”, value = NULL ) )
create.matrix.runif.DS.4 <- function(no.rows = 11, no.columns = 13, min = .Machine$double.xmin, max = .Machine$double.xmax) { outcome <- FunctionOutcome$new() tryCatch( {outcome$set(outcome$SUCCESS,"",.create.matrix(no.rows, no.columns, min, max))}, warning = function(warning) outcome$set(outcome$WARNING,warning,“NULL”), error = function(error) outcome$set(outcome$FAIL,error,“NULL”), finally = {return(outcome)} ) }
.create.matrix <- function(no.rows = 11, no.columns = 13, min = .Machine$double.xmin, max = .Machine$double.xmax) { result <- NULL if (!is.numeric(no.rows) || !is.numeric(no.columns) || !is.numeric(min) || !is.numeric(max)) { stop(“ERR:000”) }
if (no.rows < 11 || no.columns < 13) { no.rows <- 11 no.columns <- 13 warning(“WARNING:000”) }
if (min > max) #The value have been reversed { min <- max max <- min warning(“WARNING:002”) }
random.numbers <- runif(no.rows * no.columns, min = min, max = max) result <- matrix(random.numbers,no.rows,no.columns)
return(result) }
What is next? I would like some opinions of what you think about the suggestion. I would like to know what other people thing and whether it is possible to implement it.
Best wishes,
P.