From 833d801f8b190f23f7172cc0ce5567aa3529d924 Mon Sep 17 00:00:00 2001 From: Mareq Date: Sun, 18 Jan 2015 19:52:57 +0000 Subject: [PATCH 1/4] Examples explaining lexical scoping and <<- operator used in R --- scopes.R | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 scopes.R diff --git a/scopes.R b/scopes.R new file mode 100644 index 00000000000..266ab649b3b --- /dev/null +++ b/scopes.R @@ -0,0 +1,48 @@ +# modifying parent scope variable +new_counter <- function() { + i <- 0 # this is the variable being modified + function() { + i <<- i + 1 # modifies parent scope variable + i # prints parent scope variable + } +} +counter_one <- new_counter() +counter_two <- new_counter() +counter_one() # [1] 1 +counter_one() # [1] 2 +counter_two() # [1] 1 + +# parent scope variable overshadowed by the current scope variable +new_counter <- function() { + i <- 0 # this variable will be overshadowed + function() { + i <- 42 # overshadows the parent scope variable + i <<- i + 1 # modifies current scope variable + i # prints current scope variable + } +} +counter_one <- new_counter() +counter_two <- new_counter() +counter_one() # [1] 43 +counter_one() # [1] 43 +counter_two() # [1] 43 + +# modified example from 02.10 Scoping Rules: R Scoping Rules +y <- 10 +f <- function(x) { + y <- 2 # overshadows the global scope variable + y^2 + g(x) # uses current scope variable (value 2) +} +g <- function(x) { + y <<- y + 42 # modifies gloval scope variable (42 added to y, which is 10 at the beginning) + x * y # uses global scope variable (value 42), because g is defined in global environment +} +f(3) # 2^2 + 3*52 = 160 +y # 42 (changed by call to g) +f(3) # 2^2 + 3*94 = 286 +y # 94 (changed by call to g) + + +# vim: set ts=2 sw=2 noet: + + From 814ef71353227e995f74e90fc417e8b8f18bdc52 Mon Sep 17 00:00:00 2001 From: Mareq Date: Sun, 18 Jan 2015 19:53:29 +0000 Subject: [PATCH 2/4] Disection of "special" vector object from assignment instructions --- cachevector.R | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 cachevector.R diff --git a/cachevector.R b/cachevector.R new file mode 100644 index 00000000000..ffb6da9656f --- /dev/null +++ b/cachevector.R @@ -0,0 +1,85 @@ +## Cached vector, that is able to cache its mean, +## in order to avoid recomputing it, which, might +## be costly operation in some scenarios (large +## vectors, frequent recomputation) + + +## Construct and return "special" vector object, which provides +## cache for its mean value. +## Parameters: +## * x: Vector initial value. +## Note: Code of this function is direct copy-paste from README.md +## file, without any changes. +makeVector <- function(x = numeric()) { + m <- NULL + set <- function(y) { + x <<- y + m <<- NULL + } + get <- function() x + setmean <- function(mean) m <<- mean + getmean <- function() m + list( + set = set, + get = get, + setmean = setmean, + getmean = getmean + ) +} + + +## Get mean value from "special" vector object created by 'makeVector' +## function above. If possible, the mean vaule is either retrieved +## from cache, or recomputed, cached and returned otherwise. +## Parameters: +## * x: "Special" vector object (see 'makeVector' function). +## * ...: Optional arguments to be used for recomputing mean +## value (see all but the first argument of 'mean' function). +## These arguments will be taken into account only in case +## mean value is not cached and must be recomputed. +## Note: Code of this function is direct copy-paste from README.md +## file, without any changes. +cachemean <- function(x, ...) { + m <- x$getmean() + if(!is.null(m)) { + message("getting cached data") + return(m) + } + data <- x$get() + m <- mean(data, ...) + x$setmean(m) + m +} + + +## Usage example (uncomment the code below to run this basic test). + +## create cached vector +#v <- makeVector(1:100) +## print vector contents +#v$get() +## get vector mean (will return NULL, because mean has not been set, yet) +#v$getmean() +## set vector mean to correct value +#v$setmean(mean(v$get())) +## get vector mean (will return correct value, set above) +#v$getmean() +## set vector mean to incorrect value +#v$setmean(2) +## get vector mean (will return incorrect value, set above) +#v$getmean() +## use specialized function to get mean (will return incorrect value, set above) +#cachemean(v) +## assign new value to vector (resets cached value) +#v$set(42:64) +## get vector mean (will return NULL, because mean should have been reset) +#v$getmean() +## use specialized function to compute, cache and return mean value +#cachemean(v) +## get vector mean (will return correct value, set by cachemean) +#v$getmean() + + +# vim: set ts=2 sw=2 noet: + + From e4d8d36b56762abd3af2314859f5729917ca5fe4 Mon Sep 17 00:00:00 2001 From: Mareq Date: Sun, 18 Jan 2015 19:53:59 +0000 Subject: [PATCH 3/4] Implementation of cached matrix (assignment solution) --- cachematrix.R | 104 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 7 deletions(-) diff --git a/cachematrix.R b/cachematrix.R index a50be65aa44..15ed0b3a8fc 100644 --- a/cachematrix.R +++ b/cachematrix.R @@ -1,15 +1,105 @@ -## Put comments here that give an overall description of what your -## functions do +## Following set of functions provides means to construct "special" +## matrix object, allowing to cache its inverse matrix value using +## its lexical scope. This enables user to avoid potentially costly +## recomputation of inverse matrix. -## Write a short comment describing this function -makeCacheMatrix <- function(x = matrix()) { +## Construct and return "special" matrix object, which provides +## cache for its inverse matrix value. +## Parameters: +## * m: Matrix initial value. +makeCacheMatrix <- function(m = matrix()) { + # cached inverse matrix value + inverse <- NULL -} + # function: set matrix value (has to reset cached inverse matrix) + set <- function(x) { + m <<- x + inverse <<- NULL + } + + # function: get matrix value + get <- function() { + m + } + # function: set cached inverse matrix value + setInverse <- function(x) { + inverse <<- x + } -## Write a short comment describing this function + # function: get cached inverse matrix value + getInverse <- function() { + inverse + } + + # construct and return matrix object + list( + set = set, + get = get, + setInverse = setInverse, + getInverse = getInverse + ) +} + +## Get inverse matrix value from "special" matrix object created +## by 'makeCacheMatrix' function above. If possible, the inverse +## matrix vaule is either retrieved from cache, or recomputed, +## cached and returned otherwise. +## Parameters: +## * x: "Special" matrix object (see 'makeCacheMatrix' function). +## * ...: Optional arguments to be used for recomputing inverse +## matrix value (see all but the first argument of 'solve' +## function). These arguments will be taken into account +## only in case inverse matrix value is not cached and must +## be recomputed. cacheSolve <- function(x, ...) { - ## Return a matrix that is the inverse of 'x' + # get cached inverse matrix + inverse <- x$getInverse() + + # check cached inverse matrix and return it, if valid + if(!is.null(inverse)) { + message("getting cached data") + return(inverse) + } + + # compute inverse matrix, chache and return it, otherwise + data <- x$get() + inverse <- solve(data, ...) + x$setInverse(inverse) + inverse } + + +## Usage example (uncomment the code below to run this basic test). + +## create cached matrix +#m <- makeCacheMatrix(matrix(1:4, 2, 2)) +## print matrix +#m$get() +## get matrix inverse (will return NULL, because inverse has not been set, yet) +#m$getInverse() +## set matrix inverse to correct value +#m$setInverse(solve(m$get())) +## get matrix inverse (will return correct value, set above) +#m$getInverse() +## set matrix inverse to incorrect value +#m$setInverse(matrix(4:1, 2, 2)) +## get matrix inverse (will return incorrect value, set above) +#m$getInverse() +## use specialized function to get matrix inverse (will return incorrect vaue, set above) +#cacheSolve(m) +## assign new value to matrix (resets cached value) +#m$set(matrix(2:5, 2, 2)) +## get matrix inverse (will return NULL, because inverse should have been reset) +#m$getInverse() +## use specialized function to compute, cache and return inverse value +#cacheSolve(m) +## get matrix inverse (will return correct value, set by cacheinverse) +#m$getInverse() + + +# vim: set ts=2 sw=2 noet: + + From 18fbe7d7d0f32d65e24b25ae59d94bcc592bbc50 Mon Sep 17 00:00:00 2001 From: Mareq Date: Mon, 19 Jan 2015 18:47:23 +0000 Subject: [PATCH 4/4] Fixed errorneous explanations of <<- operator example --- scopes.R | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scopes.R b/scopes.R index 266ab649b3b..51f50372e56 100644 --- a/scopes.R +++ b/scopes.R @@ -17,15 +17,15 @@ new_counter <- function() { i <- 0 # this variable will be overshadowed function() { i <- 42 # overshadows the parent scope variable - i <<- i + 1 # modifies current scope variable + i <<- i + 1 # modifies parent scope variable i # prints current scope variable } } counter_one <- new_counter() counter_two <- new_counter() -counter_one() # [1] 43 -counter_one() # [1] 43 -counter_two() # [1] 43 +counter_one() # [1] 42 +counter_one() # [1] 42 +counter_two() # [1] 42 # modified example from 02.10 Scoping Rules: R Scoping Rules y <- 10