Programming Style
A programming style guide is a set of conventions and best practices for writing code. It outlines the preferred syntax, formatting, and structural rules that developers should follow when coding. This lessons provides common style preferences and programming guidelines for R programming – they are in many ways similar to those for Python.
Here’s why it’s important for programming teams to have a style guide:
Consistency
A style guide ensures that all team members write code in a uniform manner. This consistency makes the codebase easier to read and understand, regardless of who wrote the code. It helps new team members quickly acclimate to the project by providing a clear set of rules to follow.
Readability
When code follows a consistent style, it becomes more readable. Readable code is easier to debug, review, and maintain. It reduces the cognitive load on developers, allowing them to focus on the logic and functionality rather than deciphering different coding styles.
Maintainability
A unified coding style simplifies the process of maintaining and updating the codebase. It’s easier to identify and fix bugs or add new features when the code adheres to a predictable structure. This is particularly important in large projects where multiple developers are involved.
Collaboration
A style guide facilitates collaboration among team members. When everyone follows the same conventions, merging code from different developers becomes smoother. It minimizes conflicts and discrepancies, ensuring that the integrated code functions correctly.
Quality
Adhering to a style guide can improve the overall quality of the code. It encourages best practices such as proper indentation, meaningful variable names, and thorough documentation. High-quality code is more reliable and less prone to errors.
Efficiency
By providing clear guidelines, a style guide helps streamline the coding process. Developers spend less time debating over formatting choices and more time focusing on solving problems. It also speeds up code reviews, as reviewers can focus on the logic rather than stylistic issues.
Professionalism
A well-defined style guide reflects a level of professionalism and discipline within a team. It demonstrates a commitment to producing clean, maintainable code, which can be crucial for stakeholder confidence and project success.
In summary, a programming style guide is essential for ensuring consistency, readability, maintainability, collaboration, code quality, efficiency, and professionalism within a development team. It serves as a foundation for writing clean, efficient, and reliable code, ultimately contributing to the success of a software project.
Naming Conventions
In R, the naming of variables, functions, and other identifiers should follow a consistent pattern to enhance readability and avoid confusion. Typically, snake_case is preferred for variable and function names. For example, use data_frame
or data.frame
instead of dataFrame
or DataFrame
. Many seasoned R programmers prefer the dot or period as a separator in “snake_case” while the underscore is more common in other languages. One common problem with using dot is that this is confusing to programmers from languages like Python, Java, and C++ where the dot is the object member access operator (which in R is $).
Having said this, you likely see many of my examples use camelCase, i.e, getCurrentDir()
instead of get_current_dir()
– that is because many programmers prefer that style and have taken it from my programming style in C++ and Java. The actual style does not matter much as long as there is consistency.
Constants are generally written in ALL_CAPS, such as MAX_ITERATIONS
or MAX.ITERATIONS
.
Opening Braces
In R, most programmers prefer to have the opening brace on the same line as the start of the block statement, e.g.,
calculate_mean <- function(values) {
sum_values <- sum(values)
n <- length(values)
mean_value <- sum_values / n
return(mean_value)
}
rather than
calculate_mean <- function(values)
{
sum_values <- sum(values)
n <- length(values)
mean_value <- sum_values / n
return(mean_value)
}
Functions and Modularity
Functions should be small, focused, and perform a single task. This makes them easier to test and reuse. Avoid writing long, monolithic functions. Instead, break down the problem into smaller, manageable functions.
Error Handling
Robust error handling is essential. Use functions like stop()
, warning()
, and tryCatch()
to handle errors gracefully. Providing meaningful error messages helps users understand what went wrong.
calculate_mean <- function(values) {
if (!is.numeric(values)) {
stop("Input must be a numeric vector")
}
if (length(values) == 0) {
stop("Input vector must not be empty")
}
sum_values <- sum(values)
n <- length(values)
mean_value <- sum_values / n
return(mean_value)
}
Code Efficiency
While writing R code, consider the efficiency of your operations, especially when working with large datasets. Vectorized operations are preferred over loops due to their performance benefits. For example, use apply()
, sapply()
, or lapply()
instead of for
loops whenever possible.
Package Management
When writing scripts or packages, it is essential to manage dependencies properly. Use the library()
function to load required packages at the beginning of your script. For packages, include dependencies in the DESCRIPTION file.
library(dplyr)
library(ggplot2)
Documentation
Proper documentation is vital for both user comprehension and future maintenance. Use Roxygen2 comments to document functions in packages. This provides a standardized way to include descriptions, parameters, and examples.
#' Calculate Mean
#'
#' This function calculates the mean of a numeric vector.
#'
#' @param values A numeric vector.
#' @return The mean of the input vector.
#' @export
calculate_mean <- function(values) {
sum_values <- sum(values)
n <- length(values)
mean_value <- sum_values / n
return(mean_value)
}
Consistency
Maintaining consistency throughout your codebase is essential. This includes consistent naming conventions, formatting, and commenting styles. Consistency makes your code easier to read and maintain, especially when collaborating with others.
By following these guidelines, you can ensure that your R code is readable, maintainable, and efficient. These practices not only improve the quality of your code but also facilitate collaboration and long-term maintenance.
Summary
When programming in R, it’s important to follow certain style guidelines to ensure code readability and maintainability. Use snake_case for naming variables and functions, and ALL_CAPS for constants. Indent code with two spaces and avoid tabs. Comment judiciously, providing explanations for complex logic without cluttering the code. Write small, focused functions and handle errors gracefully with meaningful messages. Prioritize vectorized operations over loops for efficiency. Manage package dependencies properly, loading required packages at the script’s start. Document functions thoroughly using Roxygen2 comments, and maintain consistency in naming, formatting, and commenting across the codebase. These practices enhance code quality and facilitate collaboration.
LS0tCnRpdGxlOiAiUHJvZ3JhbW1pbmcgU3R5bGUgR3VpZGUgZm9yIFIiCnBhcmFtczoKICBjYXRlZ29yeTogNgogIG51bWJlcjogMjA2CiAgdGltZTogMjAKICBsZXZlbDogYmVnaW5uZXIKICB0YWdzOiAicixtYXJrZG93bixsaXRlcmF0ZSBwcm9ncmFtbWluZyIKICBkZXNjcmlwdGlvbjogIlByb3ZpZGVzIHN0eWxlIHJlY29tbWVuZGF0aW9ucyBmb3IgUiBwcm9ncmFtbWluZy4iCmRhdGU6ICI8c21hbGw+YHIgU3lzLkRhdGUoKWA8L3NtYWxsPiIKYXV0aG9yOiAiPHNtYWxsPk1hcnRpbiBTY2hlZGxiYXVlcjwvc21hbGw+IgplbWFpbDogIm0uc2NoZWRsYmF1ZXJAbmV1LmVkdSIKYWZmaWxpdGF0aW9uOiAiTm9ydGhlYXN0ZXJuIFVuaXZlcnNpdHkiCm91dHB1dDogCiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvbGxhcHNlZDogZmFsc2UKICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBzcGFjZWxhYgogICAgaGlnaGxpZ2h0OiB0YW5nbwotLS0KCi0tLQp0aXRsZTogIjxzbWFsbD5gciBwYXJhbXMkY2F0ZWdvcnlgLmByIHBhcmFtcyRudW1iZXJgPC9zbWFsbD48YnIvPjxzcGFuIHN0eWxlPSdjb2xvcjogIzJFNDA1MzsgZm9udC1zaXplOiAwLjllbSc+YHIgcm1hcmtkb3duOjptZXRhZGF0YSR0aXRsZWA8L3NwYW4+IgotLS0KCmBgYHtyIGNvZGU9eGZ1bjo6cmVhZF91dGY4KHBhc3RlMChoZXJlOjpoZXJlKCksJy9SL19pbnNlcnQyREIuUicpKSwgaW5jbHVkZSA9IEZBTFNFfQpgYGAKCiMjIFByb2dyYW1taW5nIFN0eWxlCgpBIHByb2dyYW1taW5nIHN0eWxlIGd1aWRlIGlzIGEgc2V0IG9mIGNvbnZlbnRpb25zIGFuZCBiZXN0IHByYWN0aWNlcyBmb3Igd3JpdGluZyBjb2RlLiBJdCBvdXRsaW5lcyB0aGUgcHJlZmVycmVkIHN5bnRheCwgZm9ybWF0dGluZywgYW5kIHN0cnVjdHVyYWwgcnVsZXMgdGhhdCBkZXZlbG9wZXJzIHNob3VsZCBmb2xsb3cgd2hlbiBjb2RpbmcuIFRoaXMgbGVzc29ucyBwcm92aWRlcyBjb21tb24gc3R5bGUgcHJlZmVyZW5jZXMgYW5kIHByb2dyYW1taW5nIGd1aWRlbGluZXMgZm9yIFIgcHJvZ3JhbW1pbmcgLS0gdGhleSBhcmUgaW4gbWFueSB3YXlzIHNpbWlsYXIgdG8gdGhvc2UgZm9yIFB5dGhvbi4KCkhlcmXigJlzIHdoeSBpdOKAmXMgaW1wb3J0YW50IGZvciBwcm9ncmFtbWluZyB0ZWFtcyB0byBoYXZlIGEgc3R5bGUgZ3VpZGU6CgojIyMgQ29uc2lzdGVuY3kKCkEgc3R5bGUgZ3VpZGUgZW5zdXJlcyB0aGF0IGFsbCB0ZWFtIG1lbWJlcnMgd3JpdGUgY29kZSBpbiBhIHVuaWZvcm0gbWFubmVyLiBUaGlzIGNvbnNpc3RlbmN5IG1ha2VzIHRoZSBjb2RlYmFzZSBlYXNpZXIgdG8gcmVhZCBhbmQgdW5kZXJzdGFuZCwgcmVnYXJkbGVzcyBvZiB3aG8gd3JvdGUgdGhlIGNvZGUuIEl0IGhlbHBzIG5ldyB0ZWFtIG1lbWJlcnMgcXVpY2tseSBhY2NsaW1hdGUgdG8gdGhlIHByb2plY3QgYnkgcHJvdmlkaW5nIGEgY2xlYXIgc2V0IG9mIHJ1bGVzIHRvIGZvbGxvdy4KCiMjIyBSZWFkYWJpbGl0eQoKV2hlbiBjb2RlIGZvbGxvd3MgYSBjb25zaXN0ZW50IHN0eWxlLCBpdCBiZWNvbWVzIG1vcmUgcmVhZGFibGUuIFJlYWRhYmxlIGNvZGUgaXMgZWFzaWVyIHRvIGRlYnVnLCByZXZpZXcsIGFuZCBtYWludGFpbi4gSXQgcmVkdWNlcyB0aGUgY29nbml0aXZlIGxvYWQgb24gZGV2ZWxvcGVycywgYWxsb3dpbmcgdGhlbSB0byBmb2N1cyBvbiB0aGUgbG9naWMgYW5kIGZ1bmN0aW9uYWxpdHkgcmF0aGVyIHRoYW4gZGVjaXBoZXJpbmcgZGlmZmVyZW50IGNvZGluZyBzdHlsZXMuCgojIyMgTWFpbnRhaW5hYmlsaXR5CgpBIHVuaWZpZWQgY29kaW5nIHN0eWxlIHNpbXBsaWZpZXMgdGhlIHByb2Nlc3Mgb2YgbWFpbnRhaW5pbmcgYW5kIHVwZGF0aW5nIHRoZSBjb2RlYmFzZS4gSXTigJlzIGVhc2llciB0byBpZGVudGlmeSBhbmQgZml4IGJ1Z3Mgb3IgYWRkIG5ldyBmZWF0dXJlcyB3aGVuIHRoZSBjb2RlIGFkaGVyZXMgdG8gYSBwcmVkaWN0YWJsZSBzdHJ1Y3R1cmUuIFRoaXMgaXMgcGFydGljdWxhcmx5IGltcG9ydGFudCBpbiBsYXJnZSBwcm9qZWN0cyB3aGVyZSBtdWx0aXBsZSBkZXZlbG9wZXJzIGFyZSBpbnZvbHZlZC4KCiMjIyBDb2xsYWJvcmF0aW9uCgpBIHN0eWxlIGd1aWRlIGZhY2lsaXRhdGVzIGNvbGxhYm9yYXRpb24gYW1vbmcgdGVhbSBtZW1iZXJzLiBXaGVuIGV2ZXJ5b25lIGZvbGxvd3MgdGhlIHNhbWUgY29udmVudGlvbnMsIG1lcmdpbmcgY29kZSBmcm9tIGRpZmZlcmVudCBkZXZlbG9wZXJzIGJlY29tZXMgc21vb3RoZXIuIEl0IG1pbmltaXplcyBjb25mbGljdHMgYW5kIGRpc2NyZXBhbmNpZXMsIGVuc3VyaW5nIHRoYXQgdGhlIGludGVncmF0ZWQgY29kZSBmdW5jdGlvbnMgY29ycmVjdGx5LgoKIyMjIFF1YWxpdHkKCkFkaGVyaW5nIHRvIGEgc3R5bGUgZ3VpZGUgY2FuIGltcHJvdmUgdGhlIG92ZXJhbGwgcXVhbGl0eSBvZiB0aGUgY29kZS4gSXQgZW5jb3VyYWdlcyBiZXN0IHByYWN0aWNlcyBzdWNoIGFzIHByb3BlciBpbmRlbnRhdGlvbiwgbWVhbmluZ2Z1bCB2YXJpYWJsZSBuYW1lcywgYW5kIHRob3JvdWdoIGRvY3VtZW50YXRpb24uIEhpZ2gtcXVhbGl0eSBjb2RlIGlzIG1vcmUgcmVsaWFibGUgYW5kIGxlc3MgcHJvbmUgdG8gZXJyb3JzLgoKIyMjIEVmZmljaWVuY3kKCkJ5IHByb3ZpZGluZyBjbGVhciBndWlkZWxpbmVzLCBhIHN0eWxlIGd1aWRlIGhlbHBzIHN0cmVhbWxpbmUgdGhlIGNvZGluZyBwcm9jZXNzLiBEZXZlbG9wZXJzIHNwZW5kIGxlc3MgdGltZSBkZWJhdGluZyBvdmVyIGZvcm1hdHRpbmcgY2hvaWNlcyBhbmQgbW9yZSB0aW1lIGZvY3VzaW5nIG9uIHNvbHZpbmcgcHJvYmxlbXMuIEl0IGFsc28gc3BlZWRzIHVwIGNvZGUgcmV2aWV3cywgYXMgcmV2aWV3ZXJzIGNhbiBmb2N1cyBvbiB0aGUgbG9naWMgcmF0aGVyIHRoYW4gc3R5bGlzdGljIGlzc3Vlcy4KCiMjIyBQcm9mZXNzaW9uYWxpc20KCkEgd2VsbC1kZWZpbmVkIHN0eWxlIGd1aWRlIHJlZmxlY3RzIGEgbGV2ZWwgb2YgcHJvZmVzc2lvbmFsaXNtIGFuZCBkaXNjaXBsaW5lIHdpdGhpbiBhIHRlYW0uIEl0IGRlbW9uc3RyYXRlcyBhIGNvbW1pdG1lbnQgdG8gcHJvZHVjaW5nIGNsZWFuLCBtYWludGFpbmFibGUgY29kZSwgd2hpY2ggY2FuIGJlIGNydWNpYWwgZm9yIHN0YWtlaG9sZGVyIGNvbmZpZGVuY2UgYW5kIHByb2plY3Qgc3VjY2Vzcy4KCkluIHN1bW1hcnksIGEgcHJvZ3JhbW1pbmcgc3R5bGUgZ3VpZGUgaXMgZXNzZW50aWFsIGZvciBlbnN1cmluZyBjb25zaXN0ZW5jeSwgcmVhZGFiaWxpdHksIG1haW50YWluYWJpbGl0eSwgY29sbGFib3JhdGlvbiwgY29kZSBxdWFsaXR5LCBlZmZpY2llbmN5LCBhbmQgcHJvZmVzc2lvbmFsaXNtIHdpdGhpbiBhIGRldmVsb3BtZW50IHRlYW0uIEl0IHNlcnZlcyBhcyBhIGZvdW5kYXRpb24gZm9yIHdyaXRpbmcgY2xlYW4sIGVmZmljaWVudCwgYW5kIHJlbGlhYmxlIGNvZGUsIHVsdGltYXRlbHkgY29udHJpYnV0aW5nIHRvIHRoZSBzdWNjZXNzIG9mIGEgc29mdHdhcmUgcHJvamVjdC4KCiMjIE5hbWluZyBDb252ZW50aW9ucwoKSW4gUiwgdGhlIG5hbWluZyBvZiB2YXJpYWJsZXMsIGZ1bmN0aW9ucywgYW5kIG90aGVyIGlkZW50aWZpZXJzIHNob3VsZCBmb2xsb3cgYSBjb25zaXN0ZW50IHBhdHRlcm4gdG8gZW5oYW5jZSByZWFkYWJpbGl0eSBhbmQgYXZvaWQgY29uZnVzaW9uLiBUeXBpY2FsbHksIHNuYWtlX2Nhc2UgaXMgcHJlZmVycmVkIGZvciB2YXJpYWJsZSBhbmQgZnVuY3Rpb24gbmFtZXMuIEZvciBleGFtcGxlLCB1c2UgYGRhdGFfZnJhbWVgIG9yIGBkYXRhLmZyYW1lYCBpbnN0ZWFkIG9mIGBkYXRhRnJhbWVgIG9yIGBEYXRhRnJhbWVgLiBNYW55IHNlYXNvbmVkIFIgcHJvZ3JhbW1lcnMgcHJlZmVyIHRoZSBkb3Qgb3IgcGVyaW9kIGFzIGEgc2VwYXJhdG9yIGluICJzbmFrZV9jYXNlIiB3aGlsZSB0aGUgdW5kZXJzY29yZSBpcyBtb3JlIGNvbW1vbiBpbiBvdGhlciBsYW5ndWFnZXMuIE9uZSBjb21tb24gcHJvYmxlbSB3aXRoIHVzaW5nIGRvdCBpcyB0aGF0IHRoaXMgaXMgY29uZnVzaW5nIHRvIHByb2dyYW1tZXJzIGZyb20gbGFuZ3VhZ2VzIGxpa2UgUHl0aG9uLCBKYXZhLCBhbmQgQysrIHdoZXJlIHRoZSBkb3QgaXMgdGhlIG9iamVjdCBtZW1iZXIgYWNjZXNzIG9wZXJhdG9yICh3aGljaCBpbiBSIGlzIFwkKS4KCkhhdmluZyBzYWlkIHRoaXMsIHlvdSBsaWtlbHkgc2VlIG1hbnkgb2YgbXkgZXhhbXBsZXMgdXNlIGNhbWVsQ2FzZSwgKmkuZSosIGBnZXRDdXJyZW50RGlyKClgIGluc3RlYWQgb2YgYGdldF9jdXJyZW50X2RpcigpYCAtLSB0aGF0IGlzIGJlY2F1c2UgbWFueSBwcm9ncmFtbWVycyBwcmVmZXIgdGhhdCBzdHlsZSBhbmQgaGF2ZSB0YWtlbiBpdCBmcm9tIG15IHByb2dyYW1taW5nIHN0eWxlIGluIEMrKyBhbmQgSmF2YS4gVGhlIGFjdHVhbCBzdHlsZSBkb2VzIG5vdCBtYXR0ZXIgbXVjaCBhcyBsb25nIGFzIHRoZXJlIGlzIGNvbnNpc3RlbmN5LgoKQ29uc3RhbnRzIGFyZSBnZW5lcmFsbHkgd3JpdHRlbiBpbiBBTExfQ0FQUywgc3VjaCBhcyBgTUFYX0lURVJBVElPTlNgIG9yIGBNQVguSVRFUkFUSU9OU2AuCgojIyBDb2RlIFN0cnVjdHVyZSBhbmQgRm9ybWF0dGluZwoKV2VsbC1zdHJ1Y3R1cmVkIGNvZGUgaXMgZWFzaWVyIHRvIHJlYWQgYW5kIG1haW50YWluLiBJbmRlbnRhdGlvbiBpcyBjcnVjaWFsLCB3aXRoIHR3byBzcGFjZXMgYmVpbmcgdGhlIHN0YW5kYXJkIGZvciBlYWNoIGxldmVsIG9mIGluZGVudGF0aW9uLiBBdm9pZCB1c2luZyB0YWJzLCBhcyB0aGV5IGNhbiByZW5kZXIgZGlmZmVyZW50bHkgaW4gdmFyaW91cyBlZGl0b3JzLiBIZXJlJ3MgYW4gZXhhbXBsZToKCmBgYCByCmNhbGN1bGF0ZV9tZWFuIDwtIGZ1bmN0aW9uKHZhbHVlcykgewogIHN1bV92YWx1ZXMgPC0gc3VtKHZhbHVlcykKICBuIDwtIGxlbmd0aCh2YWx1ZXMpCiAgbWVhbl92YWx1ZSA8LSBzdW1fdmFsdWVzIC8gbgogIHJldHVybihtZWFuX3ZhbHVlKQp9CmBgYAoKIyMgT3BlbmluZyBCcmFjZXMKCkluIFIsIG1vc3QgcHJvZ3JhbW1lcnMgcHJlZmVyIHRvIGhhdmUgdGhlIG9wZW5pbmcgYnJhY2Ugb24gdGhlIHNhbWUgbGluZSBhcyB0aGUgc3RhcnQgb2YgdGhlIGJsb2NrIHN0YXRlbWVudCwgKmUuZy4qLAoKYGBgIHIKY2FsY3VsYXRlX21lYW4gPC0gZnVuY3Rpb24odmFsdWVzKSB7CiAgc3VtX3ZhbHVlcyA8LSBzdW0odmFsdWVzKQogIG4gPC0gbGVuZ3RoKHZhbHVlcykKICBtZWFuX3ZhbHVlIDwtIHN1bV92YWx1ZXMgLyBuCiAgcmV0dXJuKG1lYW5fdmFsdWUpCn0KYGBgCgpyYXRoZXIgdGhhbgoKYGBgIHIKY2FsY3VsYXRlX21lYW4gPC0gZnVuY3Rpb24odmFsdWVzKSAKewogIHN1bV92YWx1ZXMgPC0gc3VtKHZhbHVlcykKICBuIDwtIGxlbmd0aCh2YWx1ZXMpCiAgbWVhbl92YWx1ZSA8LSBzdW1fdmFsdWVzIC8gbgogIHJldHVybihtZWFuX3ZhbHVlKQp9CmBgYAoKIyMgQ29tbWVudGluZwoKQ29tbWVudHMgc2hvdWxkIGJlIHVzZWQgdG8gZXhwbGFpbiB0aGUgcHVycG9zZSBhbmQgbG9naWMgb2YgeW91ciBjb2RlLCBidXQgdGhleSBzaG91bGQgbm90IGJlIG92ZXJ1c2VkIHRvIHRoZSBwb2ludCB3aGVyZSB0aGV5IGNsdXR0ZXIgdGhlIGNvZGUuIFVzZSBgI2AgZm9yIHNpbmdsZS1saW5lIGNvbW1lbnRzIGFuZCBwbGFjZSB0aGVtIGFib3ZlIHRoZSBjb2RlIHRoZXkgcmVmZXIgdG8uIEZvciBjb21wbGV4IGxvZ2ljLCBwcm92aWRlIGEgbW9yZSBkZXRhaWxlZCBleHBsYW5hdGlvbi4KCmBgYCByCiMgRnVuY3Rpb24gdG8gY2FsY3VsYXRlIHRoZSBtZWFuIG9mIGEgbnVtZXJpYyB2ZWN0b3IKY2FsY3VsYXRlX21lYW4gPC0gZnVuY3Rpb24odmFsdWVzKSB7CiAgIyBTdW1taW5nIHVwIGFsbCB2YWx1ZXMKICBzdW1fdmFsdWVzIDwtIHN1bSh2YWx1ZXMpCiAgIyBDb3VudGluZyB0aGUgbnVtYmVyIG9mIHZhbHVlcwogIG4gPC0gbGVuZ3RoKHZhbHVlcykKICAjIENhbGN1bGF0aW5nIHRoZSBtZWFuCiAgbWVhbl92YWx1ZSA8LSBzdW1fdmFsdWVzIC8gbgogIHJldHVybihtZWFuX3ZhbHVlKQp9CmBgYAoKIyMgRnVuY3Rpb25zIGFuZCBNb2R1bGFyaXR5CgpGdW5jdGlvbnMgc2hvdWxkIGJlIHNtYWxsLCBmb2N1c2VkLCBhbmQgcGVyZm9ybSBhIHNpbmdsZSB0YXNrLiBUaGlzIG1ha2VzIHRoZW0gZWFzaWVyIHRvIHRlc3QgYW5kIHJldXNlLiBBdm9pZCB3cml0aW5nIGxvbmcsIG1vbm9saXRoaWMgZnVuY3Rpb25zLiBJbnN0ZWFkLCBicmVhayBkb3duIHRoZSBwcm9ibGVtIGludG8gc21hbGxlciwgbWFuYWdlYWJsZSBmdW5jdGlvbnMuCgojIyBFcnJvciBIYW5kbGluZwoKUm9idXN0IGVycm9yIGhhbmRsaW5nIGlzIGVzc2VudGlhbC4gVXNlIGZ1bmN0aW9ucyBsaWtlIGBzdG9wKClgLCBgd2FybmluZygpYCwgYW5kIGB0cnlDYXRjaCgpYCB0byBoYW5kbGUgZXJyb3JzIGdyYWNlZnVsbHkuIFByb3ZpZGluZyBtZWFuaW5nZnVsIGVycm9yIG1lc3NhZ2VzIGhlbHBzIHVzZXJzIHVuZGVyc3RhbmQgd2hhdCB3ZW50IHdyb25nLgoKYGBgIHIKY2FsY3VsYXRlX21lYW4gPC0gZnVuY3Rpb24odmFsdWVzKSB7CiAgaWYgKCFpcy5udW1lcmljKHZhbHVlcykpIHsKICAgIHN0b3AoIklucHV0IG11c3QgYmUgYSBudW1lcmljIHZlY3RvciIpCiAgfQogIGlmIChsZW5ndGgodmFsdWVzKSA9PSAwKSB7CiAgICBzdG9wKCJJbnB1dCB2ZWN0b3IgbXVzdCBub3QgYmUgZW1wdHkiKQogIH0KICBzdW1fdmFsdWVzIDwtIHN1bSh2YWx1ZXMpCiAgbiA8LSBsZW5ndGgodmFsdWVzKQogIG1lYW5fdmFsdWUgPC0gc3VtX3ZhbHVlcyAvIG4KICByZXR1cm4obWVhbl92YWx1ZSkKfQpgYGAKCiMjIENvZGUgRWZmaWNpZW5jeQoKV2hpbGUgd3JpdGluZyBSIGNvZGUsIGNvbnNpZGVyIHRoZSBlZmZpY2llbmN5IG9mIHlvdXIgb3BlcmF0aW9ucywgZXNwZWNpYWxseSB3aGVuIHdvcmtpbmcgd2l0aCBsYXJnZSBkYXRhc2V0cy4gVmVjdG9yaXplZCBvcGVyYXRpb25zIGFyZSBwcmVmZXJyZWQgb3ZlciBsb29wcyBkdWUgdG8gdGhlaXIgcGVyZm9ybWFuY2UgYmVuZWZpdHMuIEZvciBleGFtcGxlLCB1c2UgYGFwcGx5KClgLCBgc2FwcGx5KClgLCBvciBgbGFwcGx5KClgIGluc3RlYWQgb2YgYGZvcmAgbG9vcHMgd2hlbmV2ZXIgcG9zc2libGUuCgojIyBQYWNrYWdlIE1hbmFnZW1lbnQKCldoZW4gd3JpdGluZyBzY3JpcHRzIG9yIHBhY2thZ2VzLCBpdCBpcyBlc3NlbnRpYWwgdG8gbWFuYWdlIGRlcGVuZGVuY2llcyBwcm9wZXJseS4gVXNlIHRoZSBgbGlicmFyeSgpYCBmdW5jdGlvbiB0byBsb2FkIHJlcXVpcmVkIHBhY2thZ2VzIGF0IHRoZSBiZWdpbm5pbmcgb2YgeW91ciBzY3JpcHQuIEZvciBwYWNrYWdlcywgaW5jbHVkZSBkZXBlbmRlbmNpZXMgaW4gdGhlIERFU0NSSVBUSU9OIGZpbGUuCgpgYGAgcgpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmBgYAoKIyMgRG9jdW1lbnRhdGlvbgoKUHJvcGVyIGRvY3VtZW50YXRpb24gaXMgdml0YWwgZm9yIGJvdGggdXNlciBjb21wcmVoZW5zaW9uIGFuZCBmdXR1cmUgbWFpbnRlbmFuY2UuIFVzZSAqKlJveHlnZW4yKiogY29tbWVudHMgdG8gZG9jdW1lbnQgZnVuY3Rpb25zIGluIHBhY2thZ2VzLiBUaGlzIHByb3ZpZGVzIGEgc3RhbmRhcmRpemVkIHdheSB0byBpbmNsdWRlIGRlc2NyaXB0aW9ucywgcGFyYW1ldGVycywgYW5kIGV4YW1wbGVzLgoKYGBgIHIKIycgQ2FsY3VsYXRlIE1lYW4KIycKIycgVGhpcyBmdW5jdGlvbiBjYWxjdWxhdGVzIHRoZSBtZWFuIG9mIGEgbnVtZXJpYyB2ZWN0b3IuCiMnCiMnIEBwYXJhbSB2YWx1ZXMgQSBudW1lcmljIHZlY3Rvci4KIycgQHJldHVybiBUaGUgbWVhbiBvZiB0aGUgaW5wdXQgdmVjdG9yLgojJyBAZXhwb3J0CmNhbGN1bGF0ZV9tZWFuIDwtIGZ1bmN0aW9uKHZhbHVlcykgewogIHN1bV92YWx1ZXMgPC0gc3VtKHZhbHVlcykKICBuIDwtIGxlbmd0aCh2YWx1ZXMpCiAgbWVhbl92YWx1ZSA8LSBzdW1fdmFsdWVzIC8gbgogIHJldHVybihtZWFuX3ZhbHVlKQp9CmBgYAoKIyMgQ29uc2lzdGVuY3kKCk1haW50YWluaW5nIGNvbnNpc3RlbmN5IHRocm91Z2hvdXQgeW91ciBjb2RlYmFzZSBpcyBlc3NlbnRpYWwuIFRoaXMgaW5jbHVkZXMgY29uc2lzdGVudCBuYW1pbmcgY29udmVudGlvbnMsIGZvcm1hdHRpbmcsIGFuZCBjb21tZW50aW5nIHN0eWxlcy4gQ29uc2lzdGVuY3kgbWFrZXMgeW91ciBjb2RlIGVhc2llciB0byByZWFkIGFuZCBtYWludGFpbiwgZXNwZWNpYWxseSB3aGVuIGNvbGxhYm9yYXRpbmcgd2l0aCBvdGhlcnMuCgpCeSBmb2xsb3dpbmcgdGhlc2UgZ3VpZGVsaW5lcywgeW91IGNhbiBlbnN1cmUgdGhhdCB5b3VyIFIgY29kZSBpcyByZWFkYWJsZSwgbWFpbnRhaW5hYmxlLCBhbmQgZWZmaWNpZW50LiBUaGVzZSBwcmFjdGljZXMgbm90IG9ubHkgaW1wcm92ZSB0aGUgcXVhbGl0eSBvZiB5b3VyIGNvZGUgYnV0IGFsc28gZmFjaWxpdGF0ZSBjb2xsYWJvcmF0aW9uIGFuZCBsb25nLXRlcm0gbWFpbnRlbmFuY2UuCgojIyBTdW1tYXJ5CgpXaGVuIHByb2dyYW1taW5nIGluIFIsIGl0J3MgaW1wb3J0YW50IHRvIGZvbGxvdyBjZXJ0YWluIHN0eWxlIGd1aWRlbGluZXMgdG8gZW5zdXJlIGNvZGUgcmVhZGFiaWxpdHkgYW5kIG1haW50YWluYWJpbGl0eS4gVXNlIHNuYWtlX2Nhc2UgZm9yIG5hbWluZyB2YXJpYWJsZXMgYW5kIGZ1bmN0aW9ucywgYW5kIEFMTF9DQVBTIGZvciBjb25zdGFudHMuIEluZGVudCBjb2RlIHdpdGggdHdvIHNwYWNlcyBhbmQgYXZvaWQgdGFicy4gQ29tbWVudCBqdWRpY2lvdXNseSwgcHJvdmlkaW5nIGV4cGxhbmF0aW9ucyBmb3IgY29tcGxleCBsb2dpYyB3aXRob3V0IGNsdXR0ZXJpbmcgdGhlIGNvZGUuIFdyaXRlIHNtYWxsLCBmb2N1c2VkIGZ1bmN0aW9ucyBhbmQgaGFuZGxlIGVycm9ycyBncmFjZWZ1bGx5IHdpdGggbWVhbmluZ2Z1bCBtZXNzYWdlcy4gUHJpb3JpdGl6ZSB2ZWN0b3JpemVkIG9wZXJhdGlvbnMgb3ZlciBsb29wcyBmb3IgZWZmaWNpZW5jeS4gTWFuYWdlIHBhY2thZ2UgZGVwZW5kZW5jaWVzIHByb3Blcmx5LCBsb2FkaW5nIHJlcXVpcmVkIHBhY2thZ2VzIGF0IHRoZSBzY3JpcHQncyBzdGFydC4gRG9jdW1lbnQgZnVuY3Rpb25zIHRob3JvdWdobHkgdXNpbmcgKipSb3h5Z2VuMioqIGNvbW1lbnRzLCBhbmQgbWFpbnRhaW4gY29uc2lzdGVuY3kgaW4gbmFtaW5nLCBmb3JtYXR0aW5nLCBhbmQgY29tbWVudGluZyBhY3Jvc3MgdGhlIGNvZGViYXNlLiBUaGVzZSBwcmFjdGljZXMgZW5oYW5jZSBjb2RlIHF1YWxpdHkgYW5kIGZhY2lsaXRhdGUgY29sbGFib3JhdGlvbi4KCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgRmlsZXMgJiBSZXNvdXJjZXMKCmBgYHtyIHppcEZpbGVzLCBlY2hvPUZBTFNFfQp6aXBOYW1lID0gc3ByaW50ZigiTGVzc29uRmlsZXMtJXMtJXMuemlwIiwgCiAgICAgICAgICAgICAgICAgcGFyYW1zJGNhdGVnb3J5LAogICAgICAgICAgICAgICAgIHBhcmFtcyRudW1iZXIpCgp0ZXh0QUxpbmsgPSBwYXN0ZTAoIkFsbCBGaWxlcyBmb3IgTGVzc29uICIsIAogICAgICAgICAgICAgICBwYXJhbXMkY2F0ZWdvcnksIi4iLHBhcmFtcyRudW1iZXIpCgojIGRvd25sb2FkRmlsZXNMaW5rKCkgaXMgaW5jbHVkZWQgZnJvbSBfaW5zZXJ0MkRCLlIKa25pdHI6OnJhd19odG1sKGRvd25sb2FkRmlsZXNMaW5rKCIuIiwgemlwTmFtZSwgdGV4dEFMaW5rKSkKYGBgCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIFJlZmVyZW5jZXMKClRCRAoKIyMgRXJyYXRhCgpbTGV0IHVzIGtub3ddKGh0dHBzOi8vZm9ybS5qb3Rmb3JtLmNvbS8yMTIxODcwNzI3ODQxNTcpe3RhcmdldD0iX2JsYW5rIn0uCg==