30-Day Course
Clinical SAS → R
Day 15 of 30·Functions & Macro-like Behavior

Reusable Code: Scripts, Packages & Defensive Programming

Organizing functions, adding checks, and structuring a study codebase.

Learning objectives

  • 1Organize helper functions into sourced scripts or a study package.
  • 2Add input checks with stopifnot() and assertions.
  • 3Write informative errors and warnings.
  • 4Understand why packaged, tested functions aid validation.

Key SAS® → R comparison

TaskSAS®R
Shared macros%include / autocall librarysource('utils.R') / a package
Input check%if / error in macrostopifnot() / if(!...) stop()
Messageput 'WARNING:';warning() / message()

Code examples

Defensive derivation function
SAS®
%macro chg(base, post);
  /* limited validation available */
%mend;
R
chg <- function(post, base) {
  stopifnot(is.numeric(post), is.numeric(base))
  post - base
}

Note: stopifnot() fails fast with a clear message if inputs aren't what you expect — cheap insurance in a regulated pipeline.

Explanation

As a study grows, functions belong in sourced utility scripts or, better, a small internal package, so they are versioned, documented and unit-tested. This is the open-source analog of an autocall macro library, but with far stronger tooling for testing and review.

Defensive checks — verifying types, lengths and expected values up front — turn silent data errors into immediate, informative failures, which is exactly what validation and QC reviewers want to see.

Practice exercise

Collect three derivation helpers into a utils.R, add stopifnot() input checks to each, source the file, and write a tiny test that confirms each returns the expected value.