Data Science: Advanced-R Boot Camp Functions (a.k.a. closures)

21
Data Science: Advanced-R Boot Camp Functions (a.k.a. closures) Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD Chuck Cartledge, PhD 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 22 February 2020 1/21

Transcript of Data Science: Advanced-R Boot Camp Functions (a.k.a. closures)

Data Science: Advanced-R Boot Camp Functions (a.k.a. closures)(a.k.a. closures)
22 February 202022 February 202022 February 202022 February 202022 February 202022 February 202022 February 202022 February 202022 February 202022 February 202022 February 202022 February 202022 February 202022 February 202022 February 202022 February 202022 February 202022 February 202022 February 202022 February 202022 February 2020
1/21
2/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
Table of contents (1 of 1)
1 Intro.
3 Forms
4 Scoping
c©Old Dominion University
3/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
What are we going to cover?
We’re going to talk about:
Functions in all their glory
Their different forms
What can do they do when they are finished
c©Old Dominion University
4/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
A definition
The central computation in R is a function call, de- fined by the function object itself and the objects that are supplied as the arguments. In the functional programming model, the result is defined by another object, the value of the call.
J. Chambers [1]
Sometimes rephrased as: “To understand computations in R, two slogans are helpful:
Everything that exists is an object.
Everything that happens is a function call.”
– John Chambers
5/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
Each part of a function is visible (usually):
formals: (a.k.a the argument list)
body: the “code” inside a function
environment: the internal data structure that associates names and values
simple <- function(a, b, c=3)
{ returnValue <- c*(a+b)
6/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
Primitive functions are “secretive”:
body is not visible
formals(list)
body(list)
environment(list)
attributes(list)
attr(list,"srcref")
typeof(list)
7/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
There are different ways to call/invoke a function[4]
Some are obvious, others not.
prefix: the name of the function comes before the arguments
infix: the name of the function comes between its arguments
replacement: seem to modify their arguments in place, and have the special name xxx<-.
special: misc. language features that can also be written as prefix
## prefix
8/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
Prefix notation
The function name comes before its arguments. These constitute the majority of function calls in R.
## prefix
9/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
Infix notation
The function names come between its arguments. Infix forms are used for many mathematical operators, and for user-defined function that begin and end with the % character.
## infix
10/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
Replacement functions
Replacement functions act like they modify their arguments in place, and have the special name xxx<-. They typically have two arguments (x and value), although they can have more, and they must return the modified object.
## replacement
11/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
Special functions
“Finally, there are a bunch of language features that are usually written in special ways, but also have prefix forms.”
H. Wickham [4]
(x) (’(’(x)) # where x <- function(x){x}
{x} (’{’(x)) # where x <- function(x){x}
x[[i]] (’[[’(x, i))
if (cond) TRUE else FALSE (’if’(cond, TRUE, FALSE)) # if cond <- TRUE
repeat expr (’repeat’(expr))
12/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
Where do I look to find things?
There are specific rules, and order:
1 Name masking: names defined inside a function mask names defined outside a function.
2 Functions vs. variables: functions and variables are treated the same.
3 Fresh start: normally functions have no memory, so all searches act the same
4 Dynamic lookup: lexical scoping determines where, but not when to look for values. R looks for values when the function is run, not when the function is created.
x <- 10
levelOne <- function(){
print(x)
levelOne()
levelTwo()
R only looks one level up, then globally. c©Old Dominion University
13/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
R only uses things when it needs to
Function arguments are only evaluated if accessed (lazily).
1 Promise: consists of: (1) an expression, (2) an environment, and (3) a computed value.
2 Defaults: can be defined in terms of other arguments, or even in terms of variables defined later in the function:
3 Missing: To determine if an arguments value comes from the user or from a default, you can use missing()
y <- 10
h02 <- function(x) {
y <- 100
x + 1
14/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
Default arguments
Default doesn’t mean the same thing all the time.
The evaluation environment is slightly different for default and user supplied arguments, as default arguments are evaluated inside the function. This means that seemingly identical calls can yield different results.
h04 <- function(x = 1,
y = x * 2,
z = a + b) {
h05()
h05(ls())
You need to be thoughtful when using defaults. c©Old Dominion University
15/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
Giving back to the user
Once you are in a function, how do you get out?
Implicitly or explicitly: either the last value computed, or via the return() function
Visible or invisible: during interactive use, return values are visible or not
Errors: error indicates that something has gone wrong, and forces the user to deal with the problem.
Exit handlers: identifying single, or multiple expressions to be executed when the function exits
implicit <- function()
16/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
Exit handlers
Making sure things happen, regardless of what the function does. Sometimes a function needs to make temporary changes to the global state. To ensure that these changes are undone and that the global state is restored no matter how a function exits, use on.exit() to set up an exit handler.
Custom error handlers are beyond the scope of this bootcamp.
silly <- function(x) {
17/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
Create an “evil” function
1 Replace the current definition of the special operator: “(“
2 If the input argument is numeric increase it by 1, approximately 5% of the time.
3 Keep track of how often the function is called.
Be sure to delete the evil definition of the operator.
c©Old Dominion University
18/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
Q & A time.
Q: Why was Stonehenge abandoned? A: It wasn’t IBM compatible.
c©Old Dominion University
19/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
What have we covered?
Functions are first class objects Functions are composed of three parts:
formals (a.k.a the argument list) body the “code” inside a function environment the internal data structure that associates names and values
Functions come in different “flavors” Functions can be called in different ways
Next: Looking at environments
c©Old Dominion University
20/21
Intro. Parts of a function Forms Scoping Lazy evaluations Exiting Hands on Q & A Conclusion References Files
References (1 of 1)
[1] John Chambers, Software for data analysis: programming with r, Springer Science & Business Media, 2008.
[2] DataMentor Staff, R infix operator, https: //www.datamentor.io/r-programming/infix-operator/, 2019.
[3] Joshua Ulrich, How can i view the source code for a function?, https://stackoverflow.com/questions/19226816/how-
can-i-view-the-source-code-for-a-function, 2017.
c©Old Dominion University
Files of interest
1 Code snippets
## First codes simple <- function(a, b, c=3) { returnValue <- c*(a+b) return(returnValue) } formals(simple) body(simple) environment(simple) attributes(simple) attr(simple,"srcref") typeof(simple) ## Second codes formals(list) body(list) environment(list) attributes(list) attr(list,"srcref") typeof(list) ## Third codes x <- 3 y <- 4 '+'(x, y) x + y x <- 1:10 'second<-'<- function(x, value) { x[2] <- value x } second(x) <- 5L x ## Third codes rm(list=ls()) x <- 10 levelOne <- function() { print(sprintf("%s %.0f", as.character(match.call()[[1]]), x)) } levelTwo <- function() { x <- 23 print(sprintf("%s %.0f", as.character(match.call()[[1]]), x)) levelOne() } print(sprintf("Global value of x is:%.0f", x)) levelOne() levelTwo() ## Fourth codes rm(list=ls()) embedded <- function() { print(sprintf("Global %s()", as.character(match.call()[[1]]))) } levelOne <- function() { embedded <- function() { print(sprintf("Embedded %s()", as.character(match.call()[[1]]))) } embedded() levelTwo() } levelTwo <- function() { embedded() } embedded() levelOne() levelTwo() y <- 10 h02 <- function(x) { y <- 100 x + 1 } h02(y) h02(y <- 1000) y h04 <- function(x = 1, y = x * 2, z = a + b) { a <- 10 b <- 100 c(x, y, z) } h04() h05 <- function(x = ls()) { a <- 1 ; x } h05() h05(ls()) silly <- function(x) { on.exit(message("The first one."), add = TRUE) on.exit(message("The second one."), add = TRUE) if (x > 0){ stop("x < 0") } print(x) return (x) } silly(-1) silly( 1)
"Chuck Cartledge"