Functions allow you to compartmentalize your code, so you can use it again.

One of the most fundamentally valuable things with R is that it is totally extensible by the user community. This is why there are literally thousands of packages available for

A Basic Function

A function is just a chunck of code, which is wrapped up in a block and given a variable name.

foo <- function() { 
  cat("bar")
}

foo()
bar

The amount of code within a function can be simple like the one above or quite complex. The boundaries of the code are defined by the curly brackets.

Variable Scope

When we make a function, there is a notion of a scope for variables, which defines where variables are visible from. By default, when you start R you are given a Global Environment Scope that has all the variables and functions you’ve defined thus far. The image below is the one for this document at this stage of development.

Figure 1: Main Environment in RStudio

When we work with functions, we encapsulate code within curly-brackets. This protects their scope. Her is an example. In this function, we:

  1. Print out the value of a variable x
  2. Assign values to the variables x and z
  3. Print out the value of the variables x and z.
foo <- function( ) {
  x <- 12
  z <- "bob"
  cat("x =", x, "& z =", z ,"inside function.\n")
}

OK, so now let’s call this function.

foo()
x = 12 & z = bob inside function.
x <- 42
cat("x =", x, "before function.\n")
x = 42 before function.
foo()
x = 12 & z = bob inside function.
cat("x =", x, "after running function.\n")
x = 42 after running function.

NOTE: The value of x was changed within the function but those changes were not reflected OUTSIDE of that function. The scope of the variable x inside foo() is local to that function and anything that follows its declaration within the curly brackets of the function. However, it is invisible outside the scope of that function. This is a ‘good thing©’ because if we had visibility of all the variables in all the functions then we would either a) quickly run out of variable names to keep them unique, or b) clobber all of our existing variables by writing over them and changing their values.

Also, notice that the variable z that is assigned bob in the function is also not visible in the global environment. What happens in the function, stays in the function.

ls()
[1] "foo" "x"  
foo

x

Passing Variables.

While some functions do not take any input, most require some kind of data to work with or values to start using. These variables can are passed into the function code by including them within the function parentheses.

Any required variables are added within the function definition parentheses. These translate into the names of the variables used within the chunk.

Here is an example with one required variable, x.

foo <- function( x ) {
  print(x)
}

And it can be called by either naming the variable explicity or not.

foo( x = 23 )
[1] 23
foo( 42 )
[1] 42

However, if you require a variable to be passed and it is not given, it will result in an error.

foo()
Error in print(x): argument "x" is missing, with no default

You can get around this by making a default value for the variable, which is specified in the function definition as follows:

foo <- function( x = "Dr Dyer is my favorite professor" ) {
  print(x)
}

Then if the individual does not fill in

foo()
[1] "Dr Dyer is my favorite professor"

Retrieving Results from Functions

Similarly, many functions we write will return something to the user who is calling it. By default, a function that just does something like print some message or make some plot will return NULL

foo <- function( name = "Alice") {
  cat(name, "is in the house.")
}
foo()
Alice is in the house.

But if I try to assign a variable the results of the function, I get NULL as the value returned.

x <- foo()
Alice is in the house.
class(x)
[1] "NULL"
NULL
x
NULL

If you want to return something to the user, you need to be explicit and use the return() function to pass back the variable.

foo <- function( name = "Alice") {
  response <- paste( name, "is in the house.")
  return( response )
}
who_is_in_the_house <- foo()
who_is_in_the_house
[1] "Alice is in the house."
Alice is in the house.

You can only return one item but it can be a list a data.frame or any other R object.

Creating Functions

You can create functions for small things to be used in a single document or they can be larger more general functions that can be used all the time.

If you are going to be using a function in a single markdown document, define it in its own code chunk and then from that point down the document, it will be available to use (like we’ve done in this document).

However, if you are going to be calling a function from more than one sole Markdown document, it is probably good practice to put it in its own file. R script files contain ONLY code and this is where you should put it.

Make a new R Script file by selecting File -> New File -> R Script.

As an example, I made entered the code shown below into this script file and then saved it as summarize_levels.R in the same directory as my project (this last part is important).

Figure 2: Simple code to ake summaries from a data frame as an example function in its own file.

This code has a few sections to it. The top 9 rows are comments. These kinds of comments are denoted by a hashtag and a single quote. You do not need to have these comments in the file but when you start making a lot of function, each in their file, if you follow these instructions you can autogenerate the R help files so you (and others who may be using your code) can look at the help file.

  1. The first line has a brief description of what the script does.
  2. The next set of lines indicate Sections that can be put into the help file. These sections are denoted by an @-sign followed by a name (there are many more than the three used here).
    • @description - A more robust description of what the function does.
    • @param A listing of each parameter sent to the function and its description.
    • @return What the function returns to the user.
  3. The function body where it is actually defined. Notice, I name the function and the script file the exact same so it is easy for you to know what is in each file.

Since the function is located in another file, we need to ask R to load in the source of the code. This is done using the source() function.

source("summarize_levels.R")

Do this once and it will load the function in the current Global Environment.

Once you a few functions together, you can put them together into a library (left as an advanced topic).

LS0tCnRpdGxlOiAiRnVuY3Rpb25zIgphdXRob3I6ICJIb3cgdG8gbWFrZSBjb2RlIHdvcmsgZm9yIHlvdSIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgY3NzOiBbImh0dHBzOi8vZHllcmxhYi5naXRodWIuaW8vRU5WUy1MZWN0dXJlcy9jc3MvbmFycmF0aXZlX3N0eWxlLmNzcyJdCi0tLQoKYGBge3Igc3RhcnR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeSgga25pdHIgKQpsaWJyYXJ5KCB0aWR5dmVyc2UgKQprbml0cjo6b3B0c19jaHVuayRzZXQoIHdhcm5pbmcgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIGVycm9yID0gRkFMU0UgKQpvcHRpb25zKGRwbHlyLnN1bW1hcmlzZS5pbmZvcm09RikgCmdncGxvdDI6OnRoZW1lX3NldCggdGhlbWVfY2xhc3NpYyggYmFzZV9zaXplPTE4ICkgKQpgYGAKCj4gRnVuY3Rpb25zIGFsbG93IHlvdSB0byBjb21wYXJ0bWVudGFsaXplIHlvdXIgY29kZSwgc28geW91IGNhbiB1c2UgaXQgYWdhaW4uCgpPbmUgb2YgdGhlIG1vc3QgZnVuZGFtZW50YWxseSB2YWx1YWJsZSB0aGluZ3Mgd2l0aCBgUmAgaXMgdGhhdCBpdCBpcyB0b3RhbGx5IGV4dGVuc2libGUgYnkgdGhlIHVzZXIgY29tbXVuaXR5LiAgVGhpcyBpcyB3aHkgdGhlcmUgYXJlIGxpdGVyYWxseSB0aG91c2FuZHMgb2YgcGFja2FnZXMgYXZhaWxhYmxlIGZvciAKCgojIyBBIEJhc2ljIEZ1bmN0aW9uCgpBIGZ1bmN0aW9uIGlzIGp1c3QgYSBjaHVuY2sgb2YgY29kZSwgd2hpY2ggaXMgd3JhcHBlZCB1cCBpbiBhICpibG9jayogYW5kIGdpdmVuIGEgdmFyaWFibGUgbmFtZS4KCmBgYHtyfQpmb28gPC0gZnVuY3Rpb24oKSB7IAogIGNhdCgiYmFyIikKfQoKZm9vKCkKYGBgCgpUaGUgYW1vdW50IG9mIGNvZGUgd2l0aGluIGEgZnVuY3Rpb24gY2FuIGJlIHNpbXBsZSBsaWtlIHRoZSBvbmUgYWJvdmUgb3IgcXVpdGUgY29tcGxleC4gIFRoZSBib3VuZGFyaWVzIG9mIHRoZSBjb2RlIGFyZSBkZWZpbmVkIGJ5IHRoZSBjdXJseSBicmFja2V0cy4gCgoKIyMgVmFyaWFibGUgU2NvcGUKCldoZW4gd2UgbWFrZSBhIGZ1bmN0aW9uLCB0aGVyZSBpcyBhIG5vdGlvbiBvZiBhICpzY29wZSogZm9yIHZhcmlhYmxlcywgd2hpY2ggZGVmaW5lcyB3aGVyZSB2YXJpYWJsZXMgYXJlIHZpc2libGUgZnJvbS4gIEJ5IGRlZmF1bHQsIHdoZW4geW91IHN0YXJ0IGBSYCB5b3UgYXJlIGdpdmVuIGEgR2xvYmFsIEVudmlyb25tZW50IFNjb3BlIHRoYXQgaGFzIGFsbCB0aGUgdmFyaWFibGVzIGFuZCBmdW5jdGlvbnMgeW91J3ZlIGRlZmluZWQgdGh1cyBmYXIuICBUaGUgaW1hZ2UgYmVsb3cgaXMgdGhlIG9uZSBmb3IgdGhpcyBkb2N1bWVudCBhdCB0aGlzIHN0YWdlIG9mIGRldmVsb3BtZW50LgoKIVtGaWd1cmUgMTogTWFpbiBFbnZpcm9ubWVudCBpbiBSU3R1ZGlvXShodHRwczovL2xpdmUuc3RhdGljZmxpY2tyLmNvbS82NTUzNS81MDM5NTAxMjY5MV84ODQ0MTU4ZmU5X2NfZC5qcGcpIAoKV2hlbiB3ZSB3b3JrIHdpdGggZnVuY3Rpb25zLCB3ZSBlbmNhcHN1bGF0ZSBjb2RlIHdpdGhpbiBjdXJseS1icmFja2V0cy4gIFRoaXMgcHJvdGVjdHMgdGhlaXIgc2NvcGUuIEhlciBpcyBhbiBleGFtcGxlLiAgSW4gdGhpcyBmdW5jdGlvbiwgd2U6CgoxLiBQcmludCBvdXQgdGhlIHZhbHVlIG9mIGEgdmFyaWFibGUgYHhgICAKMi4gQXNzaWduIHZhbHVlcyB0byB0aGUgdmFyaWFibGVzIGB4YCBhbmQgYHpgCjMuIFByaW50IG91dCB0aGUgdmFsdWUgb2YgdGhlIHZhcmlhYmxlcyBgeGAgYW5kIGB6YC4KCmBgYHtyfQpmb28gPC0gZnVuY3Rpb24oICkgewogIHggPC0gMTIKICB6IDwtICJib2IiCiAgY2F0KCJ4ID0iLCB4LCAiJiB6ID0iLCB6ICwiaW5zaWRlIGZ1bmN0aW9uLlxuIikKfQpgYGAKCk9LLCBzbyBub3cgbGV0J3MgY2FsbCB0aGlzIGZ1bmN0aW9uLgoKYGBge3J9CmZvbygpCmBgYAoKCgpgYGB7cn0KeCA8LSA0MgpjYXQoInggPSIsIHgsICJiZWZvcmUgZnVuY3Rpb24uXG4iKQpmb28oKQpjYXQoInggPSIsIHgsICJhZnRlciBydW5uaW5nIGZ1bmN0aW9uLlxuIikKYGBgCgoqKk5PVEU6KiogVGhlIHZhbHVlIG9mIGB4YCB3YXMgY2hhbmdlZCB3aXRoaW4gdGhlIGZ1bmN0aW9uIGJ1dCB0aG9zZSBjaGFuZ2VzIHdlcmUgbm90IHJlZmxlY3RlZCBPVVRTSURFIG9mIHRoYXQgZnVuY3Rpb24uICBUaGUgKnNjb3BlKiBvZiB0aGUgdmFyaWFibGUgYHhgIGluc2lkZSBgZm9vKClgIGlzIGxvY2FsIHRvIHRoYXQgZnVuY3Rpb24gYW5kIGFueXRoaW5nIHRoYXQgZm9sbG93cyBpdHMgZGVjbGFyYXRpb24gd2l0aGluIHRoZSBjdXJseSBicmFja2V0cyBvZiB0aGUgZnVuY3Rpb24uICBIb3dldmVyLCBpdCBpcyAqaW52aXNpYmxlKiBvdXRzaWRlIHRoZSBzY29wZSBvZiB0aGF0IGZ1bmN0aW9uLiAgVGhpcyBpcyBhICdnb29kIHRoaW5nPHN1cD4mY29weTs8L3N1cD4nIGJlY2F1c2UgaWYgd2UgaGFkIHZpc2liaWxpdHkgb2YgYWxsIHRoZSB2YXJpYWJsZXMgaW4gYWxsIHRoZSBmdW5jdGlvbnMgdGhlbiB3ZSB3b3VsZCBlaXRoZXIgYSkgcXVpY2tseSBydW4gb3V0IG9mIHZhcmlhYmxlIG5hbWVzIHRvIGtlZXAgdGhlbSB1bmlxdWUsIG9yIGIpIGNsb2JiZXIgYWxsIG9mIG91ciBleGlzdGluZyB2YXJpYWJsZXMgYnkgd3JpdGluZyBvdmVyIHRoZW0gYW5kIGNoYW5naW5nIHRoZWlyIHZhbHVlcy4KCkFsc28sIG5vdGljZSB0aGF0IHRoZSB2YXJpYWJsZSBgemAgdGhhdCBpcyBhc3NpZ25lZCBgYm9iYCBpbiB0aGUgZnVuY3Rpb24gaXMgYWxzbyBub3QgdmlzaWJsZSBpbiB0aGUgZ2xvYmFsIGVudmlyb25tZW50LiAgKldoYXQgaGFwcGVucyBpbiB0aGUgZnVuY3Rpb24sIHN0YXlzIDx1PmluPC91PiA8dT50aGU8L3U+IDx1PmZ1bmN0aW9uPC91PiouCgpgYGB7cn0KbHMoKQpgYGAKCgoKIyMgUGFzc2luZyBWYXJpYWJsZXMuCgpXaGlsZSBzb21lIGZ1bmN0aW9ucyBkbyBub3QgdGFrZSBhbnkgaW5wdXQsIG1vc3QgcmVxdWlyZSBzb21lIGtpbmQgb2YgZGF0YSB0byB3b3JrIHdpdGggb3IgdmFsdWVzIHRvIHN0YXJ0IHVzaW5nLiBUaGVzZSB2YXJpYWJsZXMgY2FuIGFyZSBwYXNzZWQgaW50byB0aGUgZnVuY3Rpb24gY29kZSBieSBpbmNsdWRpbmcgdGhlbSB3aXRoaW4gdGhlIGZ1bmN0aW9uIHBhcmVudGhlc2VzLgoKQW55IHJlcXVpcmVkIHZhcmlhYmxlcyBhcmUgYWRkZWQgd2l0aGluIHRoZSBmdW5jdGlvbiBkZWZpbml0aW9uIHBhcmVudGhlc2VzLiAgVGhlc2UgdHJhbnNsYXRlIGludG8gdGhlIG5hbWVzIG9mIHRoZSB2YXJpYWJsZXMgdXNlZCB3aXRoaW4gdGhlIGNodW5rLiAgCgpIZXJlIGlzIGFuIGV4YW1wbGUgd2l0aCBvbmUgcmVxdWlyZWQgdmFyaWFibGUsIGB4YC4KCgpgYGB7cn0KZm9vIDwtIGZ1bmN0aW9uKCB4ICkgewogIHByaW50KHgpCn0KYGBgCgpBbmQgaXQgY2FuIGJlIGNhbGxlZCBieSBlaXRoZXIgbmFtaW5nIHRoZSB2YXJpYWJsZSBleHBsaWNpdHkgb3Igbm90LgoKYGBge3J9CmZvbyggeCA9IDIzICkKZm9vKCA0MiApCmBgYAoKSG93ZXZlciwgaWYgeW91IHJlcXVpcmUgYSB2YXJpYWJsZSB0byBiZSBwYXNzZWQgYW5kIGl0IGlzIG5vdCBnaXZlbiwgaXQgd2lsbCByZXN1bHQgaW4gYW4gZXJyb3IuCgpgYGB7ciBlcnJvcj1UUlVFfQpmb28oKQpgYGAKCgpZb3UgY2FuIGdldCBhcm91bmQgdGhpcyBieSBtYWtpbmcgYSBgZGVmYXVsdGAgdmFsdWUgZm9yIHRoZSB2YXJpYWJsZSwgd2hpY2ggaXMgc3BlY2lmaWVkIGluIHRoZSBmdW5jdGlvbiBkZWZpbml0aW9uIGFzIGZvbGxvd3M6CgpgYGB7cn0KZm9vIDwtIGZ1bmN0aW9uKCB4ID0gIkRyIER5ZXIgaXMgbXkgZmF2b3JpdGUgcHJvZmVzc29yIiApIHsKICBwcmludCh4KQp9CmBgYAoKVGhlbiBpZiB0aGUgaW5kaXZpZHVhbCBkb2VzIG5vdCBmaWxsIGluCgpgYGB7cn0KZm9vKCkKYGBgCgojIyBSZXRyaWV2aW5nIFJlc3VsdHMgZnJvbSBGdW5jdGlvbnMKClNpbWlsYXJseSwgbWFueSBmdW5jdGlvbnMgd2Ugd3JpdGUgd2lsbCByZXR1cm4gc29tZXRoaW5nIHRvIHRoZSB1c2VyIHdobyBpcyBjYWxsaW5nIGl0LiAgQnkgZGVmYXVsdCwgYSBmdW5jdGlvbiB0aGF0IGp1c3QgZG9lcyBzb21ldGhpbmcgbGlrZSBwcmludCBzb21lIG1lc3NhZ2Ugb3IgbWFrZSBzb21lIHBsb3Qgd2lsbCByZXR1cm4gYE5VTExgCgpgYGB7cn0KZm9vIDwtIGZ1bmN0aW9uKCBuYW1lID0gIkFsaWNlIikgewogIGNhdChuYW1lLCAiaXMgaW4gdGhlIGhvdXNlLiIpCn0KZm9vKCkKYGBgCgpCdXQgaWYgSSB0cnkgdG8gYXNzaWduIGEgdmFyaWFibGUgdGhlIHJlc3VsdHMgb2YgdGhlIGZ1bmN0aW9uLCBJIGdldCBgTlVMTGAgYXMgdGhlIHZhbHVlIHJldHVybmVkLgoKYGBge3J9CnggPC0gZm9vKCkKY2xhc3MoeCkKeApgYGAKCklmIHlvdSB3YW50IHRvIHJldHVybiBzb21ldGhpbmcgdG8gdGhlIHVzZXIsIHlvdSBuZWVkIHRvIGJlIGV4cGxpY2l0IGFuZCB1c2UgdGhlIGByZXR1cm4oKWAgZnVuY3Rpb24gdG8gcGFzcyBiYWNrIHRoZSB2YXJpYWJsZS4KCgpgYGB7cn0KZm9vIDwtIGZ1bmN0aW9uKCBuYW1lID0gIkFsaWNlIikgewogIHJlc3BvbnNlIDwtIHBhc3RlKCBuYW1lLCAiaXMgaW4gdGhlIGhvdXNlLiIpCiAgcmV0dXJuKCByZXNwb25zZSApCn0KYGBgCgoKYGBge3J9Cndob19pc19pbl90aGVfaG91c2UgPC0gZm9vKCkKd2hvX2lzX2luX3RoZV9ob3VzZQpgYGAKCllvdSBjYW4gb25seSByZXR1cm4gKm9uZSogaXRlbSBidXQgaXQgY2FuIGJlIGEgYGxpc3RgIGEgYGRhdGEuZnJhbWVgIG9yIGFueSBvdGhlciBgUmAgb2JqZWN0LgoKCiMgQ3JlYXRpbmcgRnVuY3Rpb25zCgpZb3UgY2FuIGNyZWF0ZSBmdW5jdGlvbnMgZm9yIHNtYWxsIHRoaW5ncyB0byBiZSB1c2VkIGluIGEgc2luZ2xlIGRvY3VtZW50IG9yIHRoZXkgY2FuIGJlIGxhcmdlciBtb3JlIGdlbmVyYWwgZnVuY3Rpb25zIHRoYXQgY2FuIGJlIHVzZWQgYWxsIHRoZSB0aW1lLiAgCgpJZiB5b3UgYXJlIGdvaW5nIHRvIGJlIHVzaW5nIGEgZnVuY3Rpb24gaW4gYSBzaW5nbGUgbWFya2Rvd24gZG9jdW1lbnQsIGRlZmluZSBpdCBpbiBpdHMgb3duIGNvZGUgY2h1bmsgYW5kIHRoZW4gZnJvbSB0aGF0IHBvaW50IGRvd24gdGhlIGRvY3VtZW50LCBpdCB3aWxsIGJlIGF2YWlsYWJsZSB0byB1c2UgKGxpa2Ugd2UndmUgZG9uZSBpbiB0aGlzIGRvY3VtZW50KS4KCkhvd2V2ZXIsIGlmIHlvdSBhcmUgZ29pbmcgdG8gYmUgY2FsbGluZyBhIGZ1bmN0aW9uIGZyb20gbW9yZSB0aGFuIG9uZSBzb2xlIE1hcmtkb3duIGRvY3VtZW50LCBpdCBpcyBwcm9iYWJseSBnb29kIHByYWN0aWNlIHRvIHB1dCBpdCBpbiBpdHMgb3duIGZpbGUuICBSIHNjcmlwdCBmaWxlcyBjb250YWluIE9OTFkgY29kZSBhbmQgdGhpcyBpcyB3aGVyZSB5b3Ugc2hvdWxkIHB1dCBpdC4KCk1ha2UgYSBuZXcgUiBTY3JpcHQgZmlsZSBieSBzZWxlY3RpbmcgKkZpbGUgLT4gTmV3IEZpbGUgLT4gUiBTY3JpcHQqLiAgCgpBcyBhbiBleGFtcGxlLCBJIG1hZGUgZW50ZXJlZCB0aGUgY29kZSBzaG93biBiZWxvdyBpbnRvIHRoaXMgc2NyaXB0IGZpbGUgYW5kIHRoZW4gc2F2ZWQgaXQgYXMgYHN1bW1hcml6ZV9sZXZlbHMuUmAgKippbiB0aGUgc2FtZSBkaXJlY3RvcnkgYXMgbXkgcHJvamVjdCoqICh0aGlzIGxhc3QgcGFydCBpcyBpbXBvcnRhbnQpLgoKIVtGaWd1cmUgMjogU2ltcGxlIGNvZGUgdG8gYWtlIHN1bW1hcmllcyBmcm9tIGEgZGF0YSBmcmFtZSBhcyBhbiBleGFtcGxlIGZ1bmN0aW9uIGluIGl0cyBvd24gZmlsZS5dKGh0dHBzOi8vbGl2ZS5zdGF0aWNmbGlja3IuY29tLzY1NTM1LzUwMzk4NDM5NTUxX2Y1NDlhODA1ODZfY19kLmpwZykKClRoaXMgY29kZSBoYXMgYSBmZXcgc2VjdGlvbnMgdG8gaXQuICBUaGUgdG9wIDkgcm93cyBhcmUgY29tbWVudHMuICBUaGVzZSBraW5kcyBvZiBjb21tZW50cyBhcmUgZGVub3RlZCBieSBhIGhhc2h0YWcgYW5kIGEgc2luZ2xlIHF1b3RlLiAgWW91IGRvIG5vdCAqbmVlZCogdG8gaGF2ZSB0aGVzZSBjb21tZW50cyBpbiB0aGUgZmlsZSBidXQgd2hlbiB5b3Ugc3RhcnQgbWFraW5nIGEgbG90IG9mIGZ1bmN0aW9uLCBlYWNoIGluIHRoZWlyIGZpbGUsIGlmIHlvdSBmb2xsb3cgdGhlc2UgaW5zdHJ1Y3Rpb25zIHlvdSBjYW4gYXV0b2dlbmVyYXRlIHRoZSBSIGhlbHAgZmlsZXMgc28geW91IChhbmQgb3RoZXJzIHdobyBtYXkgYmUgdXNpbmcgeW91ciBjb2RlKSBjYW4gbG9vayBhdCB0aGUgaGVscCBmaWxlLgoKMS4gVGhlIGZpcnN0IGxpbmUgaGFzIGEgYnJpZWYgZGVzY3JpcHRpb24gb2Ygd2hhdCB0aGUgc2NyaXB0IGRvZXMuCjIuIFRoZSBuZXh0IHNldCBvZiBsaW5lcyBpbmRpY2F0ZSAqU2VjdGlvbnMqIHRoYXQgY2FuIGJlIHB1dCBpbnRvIHRoZSBoZWxwIGZpbGUuICBUaGVzZSBzZWN0aW9ucyBhcmUgZGVub3RlZCBieSBhbiBALXNpZ24gZm9sbG93ZWQgYnkgYSBuYW1lICh0aGVyZSBhcmUgbWFueSBtb3JlIHRoYW4gdGhlIHRocmVlIHVzZWQgaGVyZSkuICAKICAgIC0gQGRlc2NyaXB0aW9uIC0gQSBtb3JlIHJvYnVzdCBkZXNjcmlwdGlvbiBvZiB3aGF0IHRoZSBmdW5jdGlvbiBkb2VzLiAgCiAgICAtIEBwYXJhbSBBIGxpc3Rpbmcgb2YgZWFjaCBwYXJhbWV0ZXIgc2VudCB0byB0aGUgZnVuY3Rpb24gYW5kIGl0cyBkZXNjcmlwdGlvbi4gIAogICAgLSBAcmV0dXJuIFdoYXQgdGhlIGZ1bmN0aW9uIHJldHVybnMgdG8gdGhlIHVzZXIuCjMuIFRoZSBmdW5jdGlvbiBib2R5IHdoZXJlIGl0IGlzIGFjdHVhbGx5IGRlZmluZWQuICBOb3RpY2UsIEkgbmFtZSB0aGUgZnVuY3Rpb24gYW5kIHRoZSBzY3JpcHQgZmlsZSB0aGUgZXhhY3Qgc2FtZSBzbyBpdCBpcyBlYXN5IGZvciB5b3UgdG8ga25vdyB3aGF0IGlzIGluIGVhY2ggZmlsZS4KCgpTaW5jZSB0aGUgZnVuY3Rpb24gaXMgbG9jYXRlZCBpbiBhbm90aGVyIGZpbGUsIHdlIG5lZWQgdG8gYXNrIGBSYCB0byBsb2FkIGluIHRoZSBzb3VyY2Ugb2YgdGhlIGNvZGUuICBUaGlzIGlzIGRvbmUgdXNpbmcgdGhlIGBzb3VyY2UoKWAgZnVuY3Rpb24uICAKCmBgYHtyfQpzb3VyY2UoInN1bW1hcml6ZV9sZXZlbHMuUiIpCmBgYAoKRG8gdGhpcyBvbmNlIGFuZCBpdCB3aWxsIGxvYWQgdGhlIGZ1bmN0aW9uIGluIHRoZSBjdXJyZW50IEdsb2JhbCBFbnZpcm9ubWVudC4KCiFbXShodHRwczovL2xpdmUuc3RhdGljZmxpY2tyLmNvbS82NTUzNS81MDM5NzgzMTQ1M19iODMzNzdkZWYwX2NfZC5qcGcpCgpPbmNlIHlvdSBhIGZldyBmdW5jdGlvbnMgdG9nZXRoZXIsIHlvdSBjYW4gcHV0IHRoZW0gdG9nZXRoZXIgaW50byBhIGxpYnJhcnkgKGxlZnQgYXMgYW4gYWR2YW5jZWQgdG9waWMpLgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg==