Context:FIT1043_MOC Β· the language fundamentals of R Β· assignment, types, and control flow before vectors/data framesProblem it solves: write and read basic R β assign variables, check/convert types, and branch/loop.
Quick Revision
π― Trigger: any R snippet β assign with the arrow operator, inspect type with class(), branch/loop with if/for/while.
β‘ Key Constraint: Rβs assignment is <- (not =), and a bare number like 10 is numeric, not integer β use as.integer() to force it.
Expected output:A holds 10; class(y) is "numeric"; conversion returns the string "8".
Assignment β x <- value (the R idiom); expressions evaluate interactively (2^3+2 β 10).
Basic types β numeric (10.5), integer (as.integer(10.5)), complex (1+2i), logical (TRUE), character ("Intro To R").
Inspect / test / convert β class(x) Β· is.integer(x) Β· as.character(x); help(c) for docs.
Control flow β if(expr){...}, for(i in 1:n){...}, while(cond){...}; break exits, next skips to the next iteration.
π Variations
for / while β for(i in 1:3) print(i^2) β 1,4,9; a while(i<=6) loop with i = i+1 prints squares.
break vs next β in for(i in 1:5), if(i==3) break prints 1,2; if(i==3) next prints 1,2,4,5.
Two ways to step a loop β filter inside (for(i in 1:15) if (i %% 2 == 1) cat(i,"\n")) or generate the right sequence (for(i in seq(1,15,2))) β seq(from, to, by) beats a modulo test when the pattern is regular. %% is the remainder operator, %/% integer division.
Printing inside loops and functions β R suppresses auto-printing there, so use cat("value:", i, "\n"); \n forces the newline (print() also works but formats less freely).
Workspace and help
Session objects β ls() lists them Β· rm(x, y) removes named ones Β· rm(list=ls()) clears everything (the standard clean-slate line at the top of a script).
Help β help("ls") (or ?ls) opens the doc β the examples at the bottom are the fastest way in; apropos("med") keyword-searches command names when you canβt recall one.
Script files β put commands in studio1.R and run with source("studio1.R") β reproducibility: the script, not the console history, is the record of an analysis. Comment with #; whitespace is ignored, so use it.
User-defined functions
myfactorial <- function(n){ if (n < 0 || floor(n) != n) # error checking FIRST { stop("n must be non-negative integer") } if (n == 0) { return(1) } # base case else { return(n * myfactorial(n-1)) } # recursive case}myfactorial(4) # 24
Definition β name <- function(args) { ... }; return(value) hands a value back.
Not usable until executed β defining a function in a script does nothing until you source it; re-running the definition overwrites the old one, so no need to delete first.
Integer test idiom β floor(n) != n detects a non-integer (β4.7β=4ξ =4.7); stop() aborts with a message.
|| vs | β || is the scalar OR for if conditions (short-circuits on the first value); | is the element-wise OR for vectors. ! negates: !is.numeric(x) reads βnot numericβ.
Returning several values with a list
findminmax <- function(x){ if (!is.numeric(x) || !is.vector(x)) { stop("Input must be a numeric vector") } retval = list() # the container retval$min = Inf; retval$max = -Inf # sentinels: any real value beats them for (i in 1:length(x)) { if (x[i] < retval$min) { retval$min = x[i] } if (x[i] > retval$max) { retval$max = x[i] } } retval$rng = retval$max - retval$min return(retval)}findminmax(c(4,3,10,33,-2,8)) # $min -2, $max 33, $rng 35
list() is Rβs multi-value return β add fields with $; lists nest freely (retval$c$g) and hold mixed types (numbers, strings, other lists).
Sentinel initialisation β starting at Inf / -Inf guarantees the first comparison replaces it β safer than seeding with x[1].
βοΈ Practice
Practice 1: Print the squares of 1..5 but skip 3, using a for loop.
Reference solution
for (i in 1:5) { if (i == 3) next print(i^2)}# 1, 4, 16, 25
Key move:next skips the current iteration; break would stop the loop entirely.
Practice 2: Write a function that returns the minimum, maximum and range of a numeric vector, rejecting non-numeric input.
Reference solution
findminmax <- function(x){ if (!is.numeric(x) || !is.vector(x)) { stop("Input must be a numeric vector") } retval = list(min = Inf, max = -Inf) for (i in 1:length(x)) { if (x[i] < retval$min) { retval$min = x[i] } if (x[i] > retval$max) { retval$max = x[i] } } retval$rng = retval$max - retval$min return(retval)}findminmax(c(4,3,10,33,-2,8)) # min -2, max 33, rng 35
Key move: three values out of one function βΉ a list; Inf/-Inf sentinels make the first comparison always fire.
β οΈ Common Mistakes
π‘ Use <-, and numbers default to numeric β 10 is "numeric", not integer; wrap with as.integer() when you truly need an integer.
π‘ break β next β break exits the loop; next only skips the rest of the current pass.
π‘ Loops and functions donβt auto-print β a bare i inside a loop shows nothing; use cat() or print().
π‘ A function must be executed before it exists β editing the definition in a script changes nothing until you source it again; a stale definition in memory is a classic phantom bug.
π‘ Recursion needs a reachable base case β myfactorial(-1) without the stop() guard recurses forever; validate the argument before the recursive call.