3
\$\begingroup\$

Playing around in R with a Edx CS50 homework. The job is meant to be done in C, I am using (the more familiar) R just for warmup.

I mainly wonder whether I am breaking any good practice/style norms overall or in any tiny detail.

initials <- function(full.name) {
  # Returns initials of a full name
  # Input will contain only letters (uppercase and/or lowercase) plus 
  # single spaces between words. Folks like Joseph Gordon-Levitt, 
  # Conan O’Brien, and David J. Malan won’t be using your program. (If only!)
  if (length(full.name) == 0) {
    stop ("Valid name please")
  } else {
    isspace  <- integer(0)
    fn.split <- unlist(strsplit(full.name, fixed = TRUE, split = ""))
    isspace  <- which(fn.split == " ")
    init     <- toupper(fn.split[c(1, (isspace+1))])
  return(paste(init, collapse = ""))
  }
}

initials("Stack Overflow")
[1] "SO"
\$\endgroup\$
  • 3
    \$\begingroup\$ If you'll consider regex, I think this will do: toupper(gsub("\\W*\\b(\\w)\\w*?\\b\\W*", "\\1", full.name)). And there must be nicer variations. \$\endgroup\$ – flodel Dec 22 '16 at 23:23
  • \$\begingroup\$ With gsubfn packge it's even shorter: gsubfn("([A-Z])[a-z]*[ ]*", ~x, full.name). \$\endgroup\$ – Iaroslav Domin Feb 3 '17 at 12:06
3
\$\begingroup\$

You have a bug. length doesn't return the length of a string, but the length of a vector. The function you need is nchar. This problem reveals that you haven't tested your program enough. Always look for corner cases and test well.

A minor thing, but when you reach a stop statement, the rest of the function will not be executed, so you could remove the else block, making the code more "flat", which is typically more readable.

As far as good practices go, in R, it's generally not recommended to use return statements, especially when there is a single point of return from the function. So I recommend to simply omit the return statement at the end of the function.

Putting the above tips together:

initials <- function(full.name) {
  # Returns initials of a full name
  # Input will contain only letters (uppercase and/or lowercase) plus 
  # single spaces between words. Folks like Joseph Gordon-Levitt, 
  # Conan O’Brien, and David J. Malan won’t be using your program. (If only!)
  if (nchar(full.name) == 0) {
    stop ("Valid name please")
  }
  isspace  <- integer(0)
  fn.split <- unlist(strsplit(full.name, fixed = TRUE, split = ""))
  isspace  <- which(fn.split == " ")
  init     <- toupper(fn.split[c(1, (isspace+1))])
  paste(init, collapse = "")
}
\$\endgroup\$
  • \$\begingroup\$ Thanks. Very useful. But it seems to me that your first statement (using return is bad) is at least contentious. See for example: stackoverflow.com/a/11895446. \$\endgroup\$ – snoram Dec 22 '16 at 19:18
  • 1
    \$\begingroup\$ @snoram fair enough. I demoted that statement, by moving to the end, and with a bit more arguments against using return. \$\endgroup\$ – janos Dec 22 '16 at 19:24
  • 1
    \$\begingroup\$ (funny, I wrote that thing you linked to... but no offense @janos, I don't always use return :-)) \$\endgroup\$ – flodel Dec 22 '16 at 23:22
  • 1
    \$\begingroup\$ @flodel funny thing is, it turns out I upvoted that linked answer a long time ago and forgot about it \$\endgroup\$ – janos Dec 22 '16 at 23:24
2
\$\begingroup\$

On top of the topics discussed in janos' answer, the coding style of your code could also be improved:


Running lintr on your code produces two notes:

  • line 5: lines should not be more than 80 characters.
  • line 12: Put spaces around all infix operators.

Although lintr sometimes produces questionable notes, both of the conventions mentioned above are supported by both Hadley Wickham's R style guide (also available in a different version) and Google's R style guide.


In line 7 there is a space before the left parenthesis. This doesn't belong there and should be deleted. Again, both of the mentioned R style guides agree on this.


The naming of your parameter, full.name, is a bit more controversial. Google's R style guide fully supports the naming style used in your code:

Don't use underscores ( _ ) or hyphens ( - ) in identifiers. Identifiers should be named according to the following conventions. The preferred form for variable names is all lower case letters and words separated with dots (variable.name), but variableName is also accepted; function names have initial capital letters and no dots (FunctionName); constants are named like functions but with an initial k.

Hadley Wickham's R style guide however explicitely discourages it:

Variable and function names should be lowercase. Use an underscore (_) to separate words within a name. [...]

Although standard R uses dots extensively in function names (contrib.url()), methods (all.equal), or class names (data.frame), it’s better to use underscores. For example, the basic S3 scheme to define a method for a class, using a generic function, would be to concatenate them with a dot, like this generic.class. This can lead to confusing methods like as.data.frame.data.frame() whereas something like print.my_class() is unambiguous.

Personally, I would recommend using underscores, exactly for the reason stated by Hadley Wickham and because I am not aware of any benefits of using dots over using underscores.


Incorporating this in the code posted by janos yields:

initials <- function(full_name) {
  # Returns initials of a full name
  # Input will contain only letters (uppercase and/or lowercase) plus
  # single spaces between words. Folks like Joseph Gordon-Levitt,
  # Conan O’Brien, and David J. Malan won’t be using your program.
  # (If only!)
  if (nchar(full_name) == 0) {
    stop("Valid name please")
  }
  isspace  <- integer(0)
  fn.split <- unlist(strsplit(full_name, fixed = TRUE, split = ""))
  isspace  <- which(fn.split == " ")
  init     <- toupper(fn.split[c(1, (isspace + 1))])
  paste(init, collapse = "")
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.