3

Are the following two equivalent, i.e. do they define the same function?

function(df) {lm(mpg ~ wt, data=df)}

and

function(df) lm(mpg ~ wt, data=df)

In particular, I am confused about why it is possible to write functions without curly brackets in R.

Are curly brackets only necessary for defining a function when the function definition extends over more than one line?

(Perhaps something about how R and Python technically support the semi-colons from C but it's considered bad practice to use them?)

This would seem to explain perhaps why people do not generally use curly brackets when defining anonymous functions, because anonymous functions are usually short and thus can fit on one line, so curly brackets are not necessary.

But would it be possible to pass anonymous functions whose definitions are longer than one line (obviously this would probably be bad practice, but that's not my point)?

If it is possible, does that require curly brackets?

Frank
  • 66,179
  • 8
  • 96
  • 180
Chill2Macht
  • 1,182
  • 3
  • 12
  • 22
  • @jogo You're right, thank you for pointing it out -- fixed in an edit – Chill2Macht Apr 25 '17 at 19:01
  • 2
    Regarding "is it possible", you can just try it. For example, `y = {x = 1; x + 2}` works, and you can figure out how by experimenting. As jogo said, the curly brackets are wrapping an expression and just happen to be useful in functions. – Frank Apr 25 '17 at 19:11
  • @jogo, please post as answer ... – Ben Bolker Apr 25 '17 at 19:13

1 Answers1

11

Your example is not about anonymous functions. It is about { and } which are not needed if there is only a single expression between them.
- An expression can be longer than a line.
- On a line there can be more than one expression (separated by semicolon).
- An anonymous function is not restricted to one line.

You can find the documentation for { as usual: help('{')

Examples:

x <- 3; y <- 4; z <- x + y  # more than one expression on a line

z <- x +
y +
2  # the expression x+y+2 extends over three lines

x <- matrix(1:30,3)
apply(x, 1, function(x) sd(x)/
median(x)) # anonymous function definition on two lines

Sometimes one has to be careful about linebreaks in the code. In some situation they are recognized as end of the syntactical unit by the interpreter. "be careful" in this situations mean:
Give the interpreter a reason to search on the next line.
This will not work:

x <- 11:15
x
[3]  # because of the linebreak it is not x[3]

But this will do:

x[
3
]
# the interpreter was searching for the ']' (till it was found)

This is the situation in which I learned my lesson:

if (...) { ... }
else { ... }     # unexpected 'else' !!!

From that time on I am coding this way:

if (...) {
   ...
} else {
   ...
}

See Unexpected 'else' in "else" error

A nonanonymous function (i.e. a named function) is nothing else than a function definition connected with an objectname by assignment:

fname <- function(...) ...

for later reuse. You can even do it in places where normally an anonymous function can be found:

x <- matrix(1:30,3)
apply(x, 1, FUN=(mysuperfunc <- function(x) sd(x)/median(x)) ) 

but this is the same with better readability:

mysuperfunc <- function(x) sd(x)/median(x)
x <- matrix(1:30,3)
apply(x, 1, FUN=mysuperfunc)
Community
  • 1
  • 1
jogo
  • 12,469
  • 11
  • 37
  • 42