Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does R allows operators to be compound expressions?

In Harold Abelson's "Structure and Interpretation of Computer Programs", which uses the Lisp programming language, one of the exercises asks you to evaluate the following code:

(define (a-plus-abs-b a b)
((if (> b 0) + -) a b))

One way to do this in R is of course:

APlusAbsB <- function(a, b){
  if(b > 0) a + b else a - b
}

Then I am repeating the as and bs.

My question is: does R allow operators to be compound expressions (e.g., if (> b 0) + -))? For example, is there a way to do something like

APlusAbsB <- function(a, b){  ## this doesn't work
  if(b > 0) "+" else "-" (a, b)    ## gives "+" or "-"
}
like image 426
Masato Nakazawa Avatar asked Aug 29 '14 20:08

Masato Nakazawa


People also ask

What is compound expressions?

A compound expression is a series of simple expressions joined by arithmetic operators. A simple expression used in a compound expression must return a numeric value.

What are expressions in R?

In R one can have objects of type "expression" . An expression contains one or more statements. A statement is a syntactically correct collection of tokens. Expression objects are special language objects which contain parsed but unevaluated R statements.

What does %/% mean in R?

%% gives Remainder. %/% gives Quotient. So 6 %% 4 = 2. In your example b %% a , it will vectorised over the values in “a”

What does & mean in R?

'&' and '&&' indicate logical AND and '|' and '||' indicate logical OR. The shorter form performs elementwise comparisons in much the same way as arithmetic operators. The longer form evaluates left to right examining only the first element of each vector. Evaluation proceeds only until the result is determined.


2 Answers

Try

APlusAbsB <- function(a, b){
  (if(b > 0) `+` else `-`)(a, b)
}

Here the if will return a function and then you call it with the parenthesis syntax. For example

APlusAbsB(1,5)
# [1] 6
APlusAbsB(1,-1)
# [1] 2
like image 165
MrFlick Avatar answered Oct 19 '22 18:10

MrFlick


Thanks to brilliant programmers I have three alternatives. I ran a benchmark test and Alternatives 1 and 2 are almost exactly the same and faster than the Alternative 3 that uses ifelse.

APlusAbsB1 <- function(a, b){(if(b > 0) `+` else `-`)(a, b)}
APlusAbsB2 <- function(a, b) {`if`(`>`(b, 0), `+`, `-`)(a, b)}
APlusAbsB3 <- function(a, b) { ifelse(b > 0, `+`, `-`)(a, b)}

microbenchmark(APlusAbsB1(sample(10, 1), sample(-10:10, 1)),
               APlusAbsB2(sample(10, 1), sample(-10:10, 1)),
               APlusAbsB3(sample(10, 1), sample(-10:10, 1)), times=10000)
Unit: microseconds
                                         expr   min    lq median    uq     max neval
 APlusAbsB1(sample(10, 1), sample(-10:10, 1)) 3.925 4.529  4.831 5.133 912.546 10000
 APlusAbsB2(sample(10, 1), sample(-10:10, 1)) 3.925 4.529  4.830 5.132 854.587 10000
 APlusAbsB3(sample(10, 1), sample(-10:10, 1)) 4.831 5.736  5.737 6.340 851.568 10000
like image 38
Masato Nakazawa Avatar answered Oct 19 '22 18:10

Masato Nakazawa