Functions: FRE6871 & FRE7241, Fall 2020
Functions: FRE6871 & FRE7241, Fall 2020
Functions in R
R functions have three components: > # Define a function with two arguments
> test_func <- function(first_arg, second_arg) { # Body
a list of formal arguments, + first_arg + second_arg # Returns last evaluated statement
+ } # end test_func
a body containing R code, >
> test_func(1, 2) # Apply the function
> args(test_func) # Display argument
an environment, >
> # Define function that uses variable from enclosure environment
An R function plus its environment is > test_func <- function(first_arg, second_arg) {
referred to as a function closures. + first_arg + second_arg + glob_var
+ } # end test_func
>
The function body should be enclosed > test_func(3, 2) # error - glob_var doesn't exist yet!
in curly braces {}, unless it contains a > glob_var <- 10 # Create glob_var
> test_func(3, 2) # Now works
single command, then it doesn’t have
to enclosed.
The function body doesn’t require a
return statement, since by default R
functions return the last statement
evaluated in the body.
args() displays the formal arguments
of a function.
value.
Exploring Functions
If a function name is called alone > # Show the function code
> plot.default
without arguments, then R displays the > # Display function
function code (but it must be on the > getAnywhere(plot.default)
search path).
Non-visible objects can’t be viewed by
calling their name.
The function getAnywhere() displays
information about R objects, including
non-visible objects.
The function getAnywhere() also
displays R objects that aren’t on the
search path.
.Primitive()
R .Internal() .Primitive()
The function getAnywhere() displays
R objects, including functions.
If a function name is called alone then
R displays the function code (but it
must be on the search path).
the user can access symbols from a
package that isn’t attached using the
double-colon operator
tools::file ext
The function getAnywhere() also
displays R objects that aren’t on the
search path.
Function Environments
When a function is called, a new > glob_var <- 1 # Define a global variable
> ls(environment()) # Get all variables in environment
evaluation environment is created. > func_env <- function() { # Explore function environments
+ loc_var <- 1 # Define a local variable
The evaluation environment contains + cat('objects in evaluation environment:\t',
the function arguments and locally +
+
ls(environment()), '\n')
cat('objects in enclosing environment:\t',
defined variables. + ls(parent.env(environment())), '\n')
+ cat('this is the enclosing environment:')
R evaluates variables inside functions + parent.env(environment()) # Return enclosing environment
+ } # end func_env
by searching first in the evaluation > func_env()
environment, then the enclosure >
> environment(func_env)
environment, then the R search path. > environment(print) # Package namespace is the enclosure
Argument Passing in R
In general, arguments can be passed into > a <- 1 # Define a variable
> # New variable "b" points to value of "a"
functions either by value or by reference. > b <- a # Define a new variable
> # When "b" is modified, R makes a copy of it
When an argument is passed by value, then a > b <- b+1
copy of that argument is passed to the function. >
>
# Function doubles its argument and returns it
double_it <- function(in_put) {
+ in_put <- 2*in_put
That way if the function modifies that + cat("input argument was doubled to:", in_put, "\n")
argument, then the original object isn’t + in_put
+ }
modified. > double_it(a)
> a # variable "a" is unchanged
When an argument is passed by reference, then
a pointer to the original object is passed to the
function. Copy-on-modify semantics has important
implications for performance and memory usage.
If the function modifies that argument, then the
original object is modified as well. http://stackoverflow.com/questions/15759117/
what-exactly-is-copy-on-modify-semantics-in-r-and-where
R uses a hybrid method of argument passing
called copy-on-modify semantics.
R passes arguments by reference, thus saving
memory space and time for copying.
But if the argument is modified within the
function, then R makes a copy of it, so that the
original object is unchanged.
Operators as Functions
Most functions in R are prefix operators (where > # Standard infix operator call syntax
> 2 + 3
the function name is followed by a list of > # Infix operator applied using prefix syntax
arguments). > "+"(2, 3)
> # Standard bracket operator
Infix operators (where the the function name >
>
vec_tor <- c(4, 3, 5, 6)
vec_tor[2]
comes in between its arguments) can also be > # Bracket operator applied using prefix syntax
> "["(vec_tor, 2)
applied using prefix syntax. >
Replacement Functions
R syntax allows assigning to the values > obj_string <- "hello"
> class(obj_string)
returned by functions, but they must > # Assign to value returned by "class" function
be defined as replacement functions. > class(obj_string) <- "string"
> class(obj_string)
replacement function names include >
>
# Define function last()
last <- function(vec_tor) {
the assignment arrow: "name<-". + vec_tor[NROW(vec_tor)]
+ } # end last
The first argument passed to the > last(1:10)
> # Define replacement function last()
replacement function is modified by > 'last<-' <- function(vec_tor, value) {
the second argument, and then it’s + vec_tor[NROW(vec_tor)] <- value
+ vec_tor
returned. + } # end last
> x <- 1:5
> last(x) <- 11
> x
Mutable States
A mutable state is an object that is > make_counter <- function() {
+ # Counter function with mutable state
preserved between function calls. + counter <- 0 # Initialize counter
+ cat('counter = ', counter)
Functions that return closures can also + function() { # Return anonymous advance function
be used for creating mutable states. + counter <<- counter + 1 # Advance counter
+ cat('counter = ', counter)
+ } # end advance function
A function evaluation environment is + } # end make_counter
only temporary and disappears after >
> advance_counter <- make_counter() # Create new counter
the function returns its value. > advance_counter() # Advance counter
> advance_counter() # Advance counter
But a closure assigned to a name > advance_counter_two <- make_counter() # Create another counter
maintains access to the environment >
>
advance_counter_two() # Advance counter two
advance_counter() # Advance counter one
in which it was created. > advance_counter_two() # Advance counter two
> advance_counter() # Advance counter one
Therefore the closure maintains access
to its parent function’s arguments and
locally defined variables.
Functionals
Functionals are functions that accept > # Func_tional accepts function name and additional argument
> func_tional <- function(func_name, in_put) {
a function or a function name (string) + # Produce function name from argument
as one of their input arguments. + func_name <- match.fun(func_name)
+ # Execute function call
Functionals are able to execute +
+
func_name(in_put)
} # end func_tional
function calls using the function > func_tional(sqrt, 4)
> # String also works because match.fun() converts it to a function
names. > func_tional("sqrt", 4)
> str(sum) # Sum() accepts multiple arguments
The function match.fun() returns a > # Func_tional can't accept indefinite number of arguments
function name that is specified by a > func_tional(sum, 1, 2, 3)
string.
Functionals that call match.fun() are
able to accept a string as a function
name, because match.fun() converts
it to a function.
match.fun() produces an error
condition if it fails to find a function
with the specified name.
Anonymous Functions
R allows defining functions without > # Simple anonymous function
> (function(x) (x + 3)) (10)
assigning a name to them.
Anonymous functions are functions
that are not assigned to a name.
Anonymous functions can be passed
as arguments to functionals.
Operator Overloading
Operator overloading refers to defining new > # Define "+" method for "character" class
> "+.character" <- function(a, b, ...) {
methods for an existing generic function. + paste(a, "plus", b)
+ } # end +.character
The "+" operator may be overloaded by defining > methods("+") # view methods for "+" operator
a new method for "character" objects. >
>
# Define variables with "character" class
char1 <- "a"
> char2 <- "b"
But for the overloading of the "+" operator to > class(char1)
work, the objects must have an explicit > char1 + char2 # Add two "character" objects - doesn't work
> attributes(char1) # Doesn't have explicit "character" class - onl
"character" class attribute assigned to them. > char1 <- structure("a", class="character")
> char2 <- structure("b", class="character")
> attributes(char1) # Now has explicit "character" class
> # Add two "character" objects
> char1 + char2
Operator Overwriting
Operator overwriting refers to redefining an > # overwrite "+" operator
> "+" = function(a, b) {
existing function. + if (is.character(a) && is.character(b)) {
+ paste(a, "plus", b)
The functions .Internal() and .Primitive() + } else {
call functions that are part of the internal code +
+ }
.Primitive("+") (a, b)
of R. + }
> methods("+") # view methods for "+" operator
Operator overwriting should be used with care, > # Add two "numeric" objects
> 1 + 2
since it may cause unintended consequences. > # Add two "character" objects
> "a" + "b"
Homework Assignment
Required
Create a function for calculating the kurtosis of a time series of returns,
Using this function calculate the kurtosis of DAX returns, and of t-distribution returns with
four degrees of freedom (use the same number of data points in both cases),
Plot the probability density of DAX returns together with t-distribution returns with four
degrees of freedom on a single plot,
Homework Assignment
Required
Create a function for calculating the kurtosis of a time series of returns,
Using this function calculate the kurtosis of DAX returns, and of t-distribution returns with
four degrees of freedom (use the same number of data points in both cases),
Plot the probability density of DAX returns together with t-distribution returns with four
degrees of freedom on a single plot,
Recommended
Read chapters 4, 5, 10 from: Introduction to R.
Additional Reading
Download R Interpreter from CRAN (Comprehensive R Archive Network)
http://cran.r-project.org/