A small program
The file runs from the top
An R file is executed from the first line to the last. There is no main function that the language looks for. A line runs when the reader reaches it.
print("The net holds still.")
What to notice. print writes a character vector, and it shows the index [1] in front of the text. The programs on this page are base R.
Try itsprintf fills a placeholder
sprintf builds a string. %d is a placeholder for an integer. The value after the format string is filled in when the line runs.
knots <- 12
print(sprintf("Knots: %d", knots))
What to notice. %d is not printed. It is replaced by 12. A plain paste of the characters %d would leave them as they are.
Try itA project is a directory
A small program can be one file. A project is a directory around it. hello.R holds the program you run. A package, later, adds a DESCRIPTION file and an R directory. This lesson stops at the script.
# reticulum-field/
# ├── hello.R
# └── README.md
#
# Rscript hello.R
print("The net holds still.")
What to notice. Try it runs the snippet, not the directory. On your own machine, Rscript hello.R runs that file from the project directory.
Try itSyntax
<- binds a name
<- gives a name to a value. Writing the name again on the left replaces what the name refers to. The right-hand side is computed first.
knots <- 12
knots <- knots + 1
print(knots)
What to notice. The first line binds 12. The second line reads that 12, adds 1, and binds the result back to the same name.
Try itA value has a type
typeof reports how a value is stored. A bare 12 is a double. 12L is an integer. Text is character. TRUE and FALSE are logical.
span <- 12
span_l <- 12L
name <- "Reticulum"
open <- TRUE
print(c(typeof(span), typeof(span_l), typeof(name), typeof(open)))
What to notice. class(12) says numeric. typeof(12) says double. numeric is the class name people use for that double. Character has no separate one-letter type.
Try itThe last value is returned
function builds a function. The body runs when you call it. The value of the last expression is what the call returns. return() can say the same thing, and you do not need it here.
meters <- function(span) {
span * 2
}
print(meters(6))
What to notice. span * 2 is the last expression, so the call returns that product. The name meters refers to the function.
Try itif chooses, for walks the values
if runs one branch. for walks each value in a vector, not each index. The braces group the lines that belong to that branch or that step.
spans <- c(3, 5, 8)
total <- 0
for (span in spans) {
if (span > 4) {
total <- total + span
}
}
print(total)
What to notice. 3 is not greater than 4, so it is skipped. 5 and 8 are added. The name span is the value itself on each step.
Try itData
A list holds named pieces
list builds a list. A name in the call becomes a name you can use with $. $ pulls out that piece.
pier <- list(name = "North", span = 12)
print(pier$span)
What to notice. pier[["span"]] is the same piece. $ is the short form when the name is a fixed word in the source.
Try itswitch picks a branch by name
switch chooses one value by matching a string to a name. The matching value is the result. If nothing matches, the result is NULL.
kind <- "star"
label <- switch(kind, star = "point", line = "edge")
print(label)
What to notice. kind is the string star, so the branch named star is chosen. The branch named line is not evaluated as the result.
Try itA vector recycles
c() builds an atomic vector. Arithmetic pairs elements. If one vector is shorter, R repeats it to the length of the longer one when the lengths fit.
spans <- c(2, 4)
print(spans + c(1, 1, 1, 1))
What to notice. The length 2 repeats twice to cover the length 4. If the longer length were not a multiple of the shorter one, R would still recycle and also warn.
Try itThe R idea
A change copies
Two names can refer to the same vector. Changing one name through [<- gives that name a new vector. The other name still sees the original.
knots <- c(12)
other <- knots
knots[1] <- 15
print(c(knots[1], other[1]))
What to notice. This is copy-on-modify. The assignment knots[1] <- 15 does not write into a shared vector. other still holds 12.
Try itAn environment is shared
An environment is the case that does not copy when you change a binding inside it. Two names can refer to one environment, and a change through one name is visible through the other.
net <- new.env()
net$knots <- 12
other <- net
net$knots <- 15
print(other$knots)
What to notice. other <- net does not duplicate the environment. net$knots <- 15 replaces a binding inside that same environment.
Try itNA is missing, NULL is absent, stop fails
NA is a missing value of some type. NULL means there is no value. stop signals an error. tryCatch can catch that error and return something else.
safe <- function(text) {
tryCatch(
{
value <- suppressWarnings(as.numeric(text))
if (is.na(value)) stop("not a number")
value
},
error = function(e) NULL
)
}
print(safe("12"))
print(is.null(safe("knot")))
What to notice. as.numeric("knot") would be NA and a warning. This function treats that NA as failure and calls stop. The error handler returns NULL, so the program continues.
Try it