Inline annotations
A #: comment repeats every parameter name of the function below it, so renaming a parameter
means editing two places. Inline annotations put each type next to the name it belongs to, which is
shorter to write and to read, and on ry’s runtime they are also checked when the code runs. The
cost is that plain Rscript cannot run a file that has them, which is why this is a separate step.
They are on by default; a project that must stay runnable by Rscript can
turn them off.
You write a type right after a name, and a function’s return type after its parameters:
apply_discount <- function(price: double, rate: double = 0.2) -> double { price * (1 - rate)}
apply_discount("100")#: fn(price: double, [rate]: double) -> doubleapply_discount <- function(price, rate = 0.2) { price * (1 - rate)}
apply_discount("100")type-mismatch
x expected `double`, found `character`Every typed page of this guide already shows this spelling in its Inline tab, and it shares one
type language with #: comments, so this page covers only what changes when you switch. Deleting
each inline annotation turns a file into the plain R program it means. That includes @pure in
front of function, the inline spelling of the #: @pure comment that
strict mode reads.
Definitions are spelled type UserId = integer and alias Row = list{id: integer}, and
@UserId(raw) creates a value of a nominal type, as custom types
shows. A binding takes @trust, @if-unknown and @new between its : and its type, as in
id: @new UserId <- 5L. type and alias are definitions only when a name follows them on the
same line, so R code that uses them as ordinary names keeps working.
When the two disagree
Section titled “When the two disagree”A statement may carry both spellings. If they give a parameter, the return, or the value different types, ry uses the inline type and warns:
#: fn(price: double, rate: double) -> doubleapply_rate <- function(price: integer, rate) price * rateannotation-mismatch
! the inline annotation gives parameter `price` the type `integer`, but the `#:` comment gives it `double`. ry uses the inline type; make the two agree, or delete one --[R/both.R:2:31] 1 | #: fn(price: double, rate: double) -> double 2 | apply_rate <- function(price: integer, rate) price * rate | ^^^^^^^ `-> > the `#:` comment's type is here --[R/both.R:1:14] 1 | #: fn(price: double, rate: double) -> double | ^^^^^^ 2 | apply_rate <- function(price: integer, rate) price * rateA #: definition directly above an inline definition of the same name is the same definition
written twice, so it is not a duplicate. ry uses the inline one and warns when the two differ:
#: @type Celsius {double}type Celsius = integerannotation-mismatch
! the inline definition of `Celsius` says `integer`, but the `#:` comment says `double`. ry uses the inline definition; make the two agree, or delete oneRunning annotated code
Section titled “Running annotated code”ry run runs annotated code on ry’s own runtime, where the annotations also become checks: an
argument of the wrong kind fails where the function was called. ry R runs it on GNU R as the plain
program it means, with the annotations erased.
scale <- function(values: double, by: double) -> double values * byscale("a", 1)$ ry run scale.RError in scale("a", 1) : argument `values` must be `double`, not `character`Execution haltedA check runs when the argument is first used, so lazy arguments stay lazy, and it tests only the
kind of value (double, character, a list, a function), not its length or class. Both commands
also print the warnings above before the code runs. The
type system reference has the full rules.
Turning inline annotations off
Section titled “Turning inline annotations off”Turn inline annotations off when every file must also run under Rscript and other R tools, which
cannot parse them:
[check]inline-annotations = falsery then reports every inline annotation it finds, so none slips into a file that must stay plain R. It warns once for the project and again at each annotation:
! inline type annotations are turned off (`[check] inline-annotations = false`), so ry does not check them and reports each one it finds
inline-annotation
! inline type annotations are turned off (`[check] inline-annotations = false`), so this one is not checked. R itself cannot run this code: delete the annotation, or turn inline annotations back onry run still runs such a file, but nothing checks the annotations. Use #: comments in such a
project. The type system reference lists every
place an inline annotation may go.