# # Things to watch when using the S language # # Author: R.W. Oldford, 2004 ################################################################################ # # 1. No clearly visible end of expression marker. # ################################################################################ fubar <- function() { 1 + 2 + 3 } snafu <- function() { 1 + 2 + 3 } fubar() snafu() # produce different answers because an invisible # character ( \newline or \return) marks the end # of an expression except of course if S can tell # by the characters so far parsed that there is more to come. # # This can be a very subtle bug if buried in the middle of some # complicated S function. (Esp. Since some editors wrap `nicely' # while others do not.) ################################################################################ # # 2. Contagion of the "string" data type. # ################################################################################ x <- matrix(1:12 , 4, 3) # is a matrix of numbers, to which I can rbind, cbind, etc. x <- rbind(x, 100) x <- cbind(x, 1000) # which is just fine. # # But suppose I want to add a variate which # takes on two values "Green" and "Blue" x <- cbind(x, c("Green", "Blue", "Green", "Green", "Blue")) # Suddenly ALL of the elements of the resulting x are strings!!! # (and so each column has become a categorical variate, or factor, for # modelling purposes! e.g. via multinom() from library(nnet) ...) # # This easily happens when, for example I rely on the filling mechanism # as when I want to construct two samples x1 <- matrix(rnorm(15),5,3) x1 <- cbind(x1,"First sample") x2 <- matrix(rnorm(21),7,3) x2 <- cbind(x2,"Second sample") xboth <- rbind(x1, x2) # Whose elements were long ago turned into strings ... # To build this properly you need to build factors # first and then cbind() them to the numerical data. ################################################################################ # # 3. Asymmetric control syntax. # ################################################################################ # This is more a matter of taste about the design of the # parsing of S expressions. # # Call to if is as if it were a function: if (predicate_test) # consequence follows immediately without a "then" appearing # but alternative *requires* "else" to precede it as in x <- 7 if (x > 3) 0 else 1 # so the following is a syntactical error if (x > 3) then 0 else 1 # as is if (x > 3) 0 1 # This is a (somewhat) natural consequence of the S parsing rule(s) # # It would also have been handy to have a natural vector based looping # by allowing the predicate_test (cond in the help file description) # to result in a vector of length > 1 whose elements are logicals. # For example, the following could be used to prduce bernoulli rvs. # (Yes, these are produced by rbinom, but that's not the point.) x <- runif(100) if (x < .5) 0 else 1