1 Structure

1.1 Implementation

1.2 Interface

The interface of a function describes how it interfaces with the world, independent of its internal implementation.

1.2.1 Inputs

  • Chapter 6: All inputs to a function should be explicit arguments. Avoid functions that suprise the user by returning different results when the inputs look the same.

  • Chapter 7: Required arguments should come before optional arguments.

  • Chapter 8: Make arguments as orthogonal as possible. Avoid complex interdependencies.

1.2.1.1 Default values

  • Chapter 10: the absence of a default value should indicate that an argument is required; the presence of a default value should indicate that an argument is optional.

  • Chapter 12: If a details argument can take one of a fixed set of possible strings, record them in the default value and use match.arg() or rlang::arg_match() inside the function.

  • Chapter 13: Default values should return the same answer when set directly.

  • Chapter 14: Default values should be short. If you have a complex calculation, either use NULL or an exported function.

  • Chapter 15: If a default value is particularly important, as has non-trivial calculation, let the user know what it is.

  • Chapter 16: Use getOption() to allow the user to set default values.

1.2.1.2 Dots

  • Chapter 18: ... should be placed between the data and details arguments.

  • Chapter 19: don’t use ... just to save the user from typing c() (unless the function is purely for data structure creation).

  • Chapter 20: carefully consider if all other arguments need a . prefix in order to reduce the chance of spurious matches.

  • Chapter 21: when using ... with S3 methods, or passing on to other functions that silently ignore mismatches, check that all inputs in ... are evaluated.

1.2.2 Output

  • Chapter 26: functions called primarily for their side-effects should invisibly return a useful value.

1.2.3 Errors

  • Chapter 27: don’t display the call when generating an error message.

  • Chapter 28: if the same error is generated by multiple functions, you should extract it out into its own function, an error constructor.

1.2.4 Side-effects

  • Chapter 30: mixing side-effects and computation in a single function makes for functions that are hard to reason about and hard to program with.

  • Chapter 31: if a function has side-effects, it should be constrained to lie at or beneath the current scope.