Skip to main content

Coming from R

If you're an R programmer, Infr is designed to feel immediately familiar. Every valid R program is already a valid Infr program. This page highlights what Infr adds and how to adopt it incrementally.

Nothing changes until you want it to​

Rename script.R to script.infr and run infr check script.infr. If your R code is valid, Infr will produce zero errors. That's the starting point.

From there, you can add types and const bindings one at a time. There's no "all or nothing" — each annotation you add gives you more safety without affecting the rest of your code.

What Infr adds to R​

const and let bindings​

R has no way to prevent reassignment. Infr adds const:

const DATA_PATH <- "data/input.csv"
DATA_PATH <- "other.csv"
# Error [infr]: Cannot reassign const binding `DATA_PATH`

Use let when you intend to reassign:

let counter <- 0
counter <- counter + 1 # OK

Plain <- still works exactly as it does in R — it's treated as mutable.

Type annotations​

Add types after variable names with :, and return types with ->:

const x: numeric <- 5
const name: character <- "Alice"

add <- function(x: numeric, y: numeric) -> numeric {
x + y
}

Infr infers types wherever possible, so annotations are optional. Add them where they help with clarity or where inference can't reach (function parameters).

Nullable types​

find_user <- function(id: integer) -> character? {
if (id > 100) NULL
else "Alice"
}

const user <- find_user(5L) # type: character?

# Infr ensures you check for NULL before using nullable values:
if (!is.null(user)) {
nchar(user) # OK — Infr narrows the type to character
}

The adoption path​

  1. Rename one .R file to .infr
  2. Run infr check — should produce zero errors
  3. Add const to bindings that shouldn't change
  4. Add type annotations to function signatures
  5. Run infr build to emit clean .R for production

Your R scripts, packages, and workflows stay the same. Infr works alongside existing R infrastructure.

Key differences from R​

FeatureRInfr
File extension.R.infr (transpiles to .R)
Variable binding<- onlyconst, let, or <-
Type annotationsNoneOptional : type syntax
Type checkingRuntime errorsCompile-time diagnostics
Function return typesImplicitOptional -> type syntax
Null safetyRuntime NULL errorsT? types with narrowing

Supported R syntax​

Infr supports all standard R syntax including:

  • R 4.1+ lambda shorthand: \(x) x + 1 (equivalent to function(x) x + 1)
  • Replacement functions: names(x) <- ..., diag(m) <- ..., levels(f) <- ...
  • Pipe operators: both |> (base R 4.1+) and %>% (magrittr)
  • Comments everywhere: including inside function call arguments

What Infr does NOT change​

  • No new runtime constructs (no classes, modules, or control flow)
  • No runtime overhead — transpiled output is plain R
  • No changes to how R packages work
  • No interference with source(), library(), or any R tooling
  • S3/S4/R5 classes work as before