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 a
s and b
s.
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 "-"
}
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.
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.
%% gives Remainder. %/% gives Quotient. So 6 %% 4 = 2. In your example b %% a , it will vectorised over the values in “a”
'&' 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.
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With