In [1]:
# This defines a vector. Specifically, an "atomic vector." 
# It is unclear why it is called "atomic."
# 'c' is short for 'combine'.
v <- c(1, 2, 3, 4, 5)
In [2]:
# Despite being composed of integers, some versions of 
# R will return that this is of type "double," which is apparently
# a placeholder (in R-speak) for "number".
typeof(v)
'double'
In [3]:
# This returns false.
# How do I get a vector of integers?
is.integer(v)
FALSE
In [4]:
# R has two kinds of assignment.
# No, it seems to have three.
# = and <- and <<-
# There are semantic differences. 
# And, you can go right-to-left or left-to-right.
#
# Joy.
three <- 3
typeof(three)

3 -> three_two
typeof(three_two)
'double'
'double'
In [5]:
# If you use =, it obeys function scope. Or, if you prefer, 
# keyword parameters are *not* keyword parameters. They're
# binding statements within the scope of the function call.
median(nums = 1:10)
# This binds num to the vector of numbers 1-10, and 
# scopes it to the call. It could be said to be equivalent to
#
# (let ([nums (range 1 10)])
#    (median nums))
# 
# to use a LISP-y syntax, but Scheme-y scoping rules.
#
# However, this violates that scope.
median(nums <- 1:10)
# This binds nums in the environment as if we had said
#
# (define nums (range 1 10))
# (median nums)
#
# So, it introduces nums to the external scope.
#
# I'm not even going to wonder what <<- does at this point.
Error in is.factor(x): argument "x" is missing, with no default
Traceback:

1. median(nums = 1:10)
2. median.default(nums = 1:10)
3. is.factor(x)
In [6]:
# That's awful. Apparently, median expects a named parameter of 'x'.
# Does this work?
median(1:10)
# Yes. Positionally, you can pass a value. But, by keyword, you
# must pass 'x'. It isn't a variable name, it is a keyword.
median(x = 1:10)
5.5
5.5
In [7]:
x
Error in eval(expr, envir, enclos): object 'x' not found
Traceback:
In [8]:
# But, this introduces x to the outer environment.
# Even though it is a keyword parameter.
# So, median() works, because we bind x, and then
# call it with the value of x. But, it will not work
# in all situations. This can lead to some really weird
# interactions at the library level...
median(x <- 1:10)
5.5
In [9]:
x
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
In [10]:
# Back to numbers.
#
# You don't get integers from integers, it turns out. When you 
# type an integer, you get a double. 
# 
# To get an integer, you must explicitly pass the integer to a function
# to coerce the value.
# http://www.r-tutor.com/r-introduction/basic-data-types/integer 
five <- as.integer(5)
typeof(five)
'integer'
In [11]:
# Can we coerce an entire vector?
# Apparently.
v2 <- as.integer(v)
typeof(v2)
'integer'
In [12]:
# This returns true.
is.double(v)
TRUE
In [13]:
# This returns true.
is.atomic(v)
TRUE
In [14]:
# Apparently, in some versions of R, this might return false?
is.vector(v)
TRUE
In [15]:
# To determine if something is a vector, we should instead use
# the inclusive conjunction of two other checks...
is.atomic(v) || is.list(v)
TRUE
In [16]:
# R will automatically coerce values. It isn't always obvious how 
# coersion will happen. For example, this will yield a vector of strings.
coerced <- c("one", 1, "two", 2, 3.0)
In [17]:
# Checking... yep.
coerced
  1. 'one'
  2. '1'
  3. 'two'
  4. '2'
  5. '3'
In [18]:
# Lists are sometimes called "recursive vectors," which only makes sense... 
# I'm not sure where that makes sense. 

# This yields a list of two lists. The vector in the second position
# is automatically coerced into a list.
a_list <- list(list(1, 2), c(3, 4))
In [19]:
# This coerces the list into a vector. I think. I'm really not clear.
# Give that atomic vectors are supposed to be homogenous, I'm not clear
# why this isn't an error. Instead, R... does something. And, I'm not confident
# it does the right thing.
a_vector <- c(list(1, 2), c(3, 4))
In [20]:
# Nope. It isn't atomic. So... does that mean it is a list?
is.atomic(a_vector)
FALSE
In [21]:
# Yep. Somehow, "combine," which appears to be used to construct vectors, will
# silently return a list if it decides it should return a list.
is.list(a_vector)
TRUE
In [22]:
# For each of these, "combine" will do *something*.
# That's foul.

# In this case, I assume it either coerces 1 to a boolean,
# or FALSE to zero. Because numbers are more flexible, R probably 
# coerces FALSE.
c(1, FALSE)
  1. 1
  2. 0
In [23]:
# We know from before that 1 becomes "1" here.
c("a", 1)
  1. 'a'
  2. '1'
In [24]:
# This must yield a list instead of a vector.
# The first list contains the number one, the second the string 'a'.
c(list(1), "a")
  1. 1
  2. 'a'
In [25]:
# And, the first element is still not an integer.
is.integer(c(list(1), "a")[0])
FALSE
In [26]:
# Is the first element of the first element an integer?
is.integer(c(list(1), "a")[0][0])
FALSE
In [27]:
# Is this broken? Can I force an error, to be sure?
is.integer(c(list(1), "a")[0][0][0])
FALSE
In [28]:
# It turns out, to reference into a list, you must use 
# the DOUBLE BRACKET operator. This is different from every
# other C-like language on the planet. Yay.
# 
# So, I have no idea what the above code actually did.
# But... it evaluated to FALSE. 
#
# Ah. It is the slice operator. 
#
# http://www.r-tutor.com/r-introduction/list
is.integer(c(list(1), "a")[[0]])
Error in c(list(1), "a")[[0]]: attempt to select less than one element in get1index <real>
Traceback:
In [29]:
# I can't access the zeroth element. Are vectors one-indexed?
is.integer(c(list(1), "a")[[1]])
FALSE
In [30]:
# Possibly. What is the 1st of the 1st?
is.integer(c(list(1), "a")[[1]][[1]])
FALSE
In [31]:
# I still have no idea what is going on. Can I make this error out?
is.integer(c(list(1), "a")[[1]][[1]][[1]])
FALSE
In [32]:
# How does this even work?
is.integer(c(list(1), "a")[[1]][[1]][[1]][[1]])
FALSE
In [33]:
# I can't imagine teaching the structure of data in this language.
In [34]:
# This... I have no idea. It might be like the first case, and 
# coerce TRUE to 1.
c(TRUE, 1L)
  1. 1
  2. 1
In [35]:
# I've begun reading about classes and objects in R. They're disgusting. 
# I would hate to have to use R to introduce students to this relatively 
# fundamental concept in programming using R. The concepts and implementation
# are essentially pulled from LISP.
#
# It turns out that a more modern encapsulation based OO system was developed
# *last year*. 
# 
# https://www.r-bloggers.com/the-r6-class-system/
# 
# I have just moved past the point where I think R should ever be taught in an
# introductory context.

# Wow. Dots are evil.
# http://www.lizsander.com/programming/2015/12/10/What-'.'-Means-in-R-and-Why-it-Matters.html
# https://www.reddit.com/r/Rlanguage/comments/61bol3/dotperiod_symbol_in_r/

# And, regarding assignment...
# https://www.r-bloggers.com/difference-between-assignment-operators-in-r/