0

I want to use optional argument logbase = NULL in my following function. However could not figure out the best practice. Any hints, please.

fn1 <- function(x, logbase = NULL){
  logbase <- ifelse(test = is.null(logbase) | 10, yes = 10, no = logbase)
  out <- log(x = x, base = logbase)
  return(out)
}

fn1(x = 10, logbase = NULL)
1

Wrong Answer

fn1(x = 10, logbase = 2)
1

Wrong Answer

fn1(x = 10, logbase = exp(1))
1
7
  • What exactly is wrong with the current approach and how would you like to improve it? Commented Apr 13, 2019 at 6:35
  • Thanks @NelsonGon for your interest in my problem. Please see my edits. Commented Apr 13, 2019 at 6:53
  • I think your function is fine, except the '| 10' always evaluates to TRUE, as converting any non-zero number to a Boolean evaluates as TRUE. You could just remove the | 10 part Commented Apr 13, 2019 at 7:02
  • 1
    @Roland test is not an object so you can't evaluate it - it's simply the first argument of the ifelse function. I think you meant | logbase == 10? If so, this can still have issues when logbase is NULL Commented Apr 13, 2019 at 7:42
  • 1
    Right. Who names arguments in ifelse? Anyway, if (is.null(logbase) || logbase == 10) ... else ... Or just set logbase = 10 as default. No, reason to use NULL as default. Commented Apr 13, 2019 at 7:55

2 Answers 2

2

My suggestion
I think the | 10 part is causing the issue, and since when logbase is 10, you get the same whether test evaluates to TRUE or FALSE, you can just remove it. I know you said in a comment this isn't working as expected, but it seems to for me - if it`s still not for you, feel free to comment.

fn1 <- function(x, logbase = NULL){
  logbase <- ifelse(test = is.null(logbase), yes = 10, no = logbase)
  out <- log(x = x, base = logbase)
  return(out)
}

fn1(x = 10, logbase = NULL)    # 1
fn1(x = 10, logbase = 2)       # 3.321928
fn1(x = 10, logbase = exp(1))  # 2.302585

What the issue with your code was
The issue is anything with | 10 will always evaluate to TRUE. This is because the | operator will convert the arguments on both sides to logical, so something like is.null(2) | 10 is equivalent to as.logical(is.null(2)) | as.logical(10) which evaluates to F | T which is T.

To be clear, | 10 is not related to logbase. What you were looking for is presumably | logbase == 10. This is fine, except when logbase is NULL, you run into issues because NULL == 10 doesn't evaluate to T or F (it's logical(0)).
You can fix this by using ||, rather than |, which would only evaluate logbase == 10 if is.null(logbase) is FALSE, because if the first half of a || is TRUE, then it simply returns TRUE without evaluating the second half.

Sign up to request clarification or add additional context in comments.

Comments

1

Here is a variant:

fn1 <- function(x, logbase = NULL){
   if(is.null(logbase)||logbase==10){
   logbase=10
    #logbase <- ifelse(test = is.null(logbase) | 10, yes = 10, no = logbase)
    out <- log(x = x, base = logbase)
    return(out)
  }
 else{
   log(x = x, base = logbase)#?exp(logbase)
 }


}

Test:

fn1(x = 10, logbase = 2)
[1] 3.321928

4 Comments

Thanks @NelsonGon for your answer. However, fn1(x = 10, logbase = NULL) and fn1(x = 10) throw the following error: Error in if (is.null(logbase) | logbase == 10) { : argument is of length zero. Any thoughts.
Try using ||, rather than |
Right! I think you just need to set base 10 as the default.
@hodgenovice: Use of || throws the error: Error in log(x = x, base = logbase) : invalid argument 'base' of length 0.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.