Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Does R Allow Omitting {} in Function Definitions?

I have a question regarding R function syntax. I've noticed that the following function works fine without curly braces {}:

sign_function <- function(x) 
  if (x > 0) "Positive" else if (x < 0) "Negative" else "Zero"

However I asked the professor and she said it is not right and that I should always add { after sign_function <- function(x) {. The code above works though.

A colleague coded the same problem as shown below, so I thought the difference is in the print part. If I add a print() statement, I need to use {} for it to work correctly:

sign_function <- function(x) {
  if (x > 0) {
    print("Positive")
    "Positive"
  } else if (x < 0) {
    print("Negative")
    "Negative"
  } else {
    print("Zero")
    "Zero"
  }
}
  1. Do I understand correctly that R allows omitting {} when the function consists of a single expression? I'd like to confirm:
  2. Is there an official explanation in R's documentation about this behavior?
  3. Are there any edge cases where omitting {} might cause unexpected behavior?
like image 606
Gaia Streparola Avatar asked Nov 22 '25 00:11

Gaia Streparola


2 Answers

The general format of a function is a header followed by a single statement that makes up the body of the function. Using braces around several statements makes them appear to the parser as a single statement.

Your colleague's function needs the braces in the if statements, but not around the body. For example, this would be fine:

sign_function <- function(x)
  if (x > 0) {
    print("Positive")
    "Positive"
  } else if (x < 0) {
    print("Negative")
    "Negative"
  } else {
    print("Zero")
    "Zero"
  }

The reason for this is that the chained if statements act like one big statement, but the code they run. e.g.

    print("Positive")
    "Positive"

is definitely two statements, so it needs to be surrounded by braces to act like just one.

So, to answer your specific questions: The R Language Definition (a manual distributed with R) describes the syntax of a function definition in section 4.1.1. As for unexpected behaviour, you might get it if you are typing in the console:

   f <- function(x) 
     if (x < 0) "negative"
     else "postive"

will give a syntax error, because if (x < 0) "negative" is a complete statement, so the parser will see that as the end of the function, and the else "positive" will be left dangling.

like image 78
user2554330 Avatar answered Nov 23 '25 17:11

user2554330


In help("function") it says that the syntax of a function defintion is

function( arglist ) expr

{ ... } has nothing intrinsically to do with functions but can be used to form a body containing more than one expression. In particular help("{") says { evaluates, i.e. runs, each enclosed statement returning the value of the last one.

Here is the bare use of {...} not connected with a function definition, if, etc. y is set to 1 and then the last expression adds it to itself and since {...} returns the value of the last expression x gets the value 2.

x <- {
  y <- 1
  y + y
}
x
## [1] 2

If there is just a single expression within {...} then it is also the last so it is just evaluated and returned but whether we surround it with {...} or not makes no difference.

x <- 3
identical(x, { x })
## [1] TRUE

Thus in the following the body is not x + 1 but is { x + 1 }. That is { and } are part of the body. The { and } are not part of the function definition but are part of the body allowing the body to be a single expression even if there were multiple statements.

f <- function(x) { x + 1 }
body(f)
## {
##     x + 1
## }

Some people use the convention of always using { ... } in function definitions because they believe it to be clearer but that is just convention and is a completely different question as to whether it must be used.

like image 22
G. Grothendieck Avatar answered Nov 23 '25 15:11

G. Grothendieck



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!