Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rlang: Error: Can't convert a function to a string

Tags:

r

tidyeval

rlang

I created a function to convert a function name to string. Version 1 func_to_string1 works well, but version 2 func_to_string2 doesn't work.

func_to_string1 <- function(fun){
    print(rlang::as_string(rlang::enexpr(fun)))
}

func_to_string2 <- function(fun){
    is.function(fun)
    print(rlang::as_string(rlang::enexpr(fun)))
}

func_to_string1 works:

> func_to_string1(sum)
[1] "sum"

func_to_string2 doesn't work.

> func_to_string2(sum)
 Error: Can't convert a primitive function to a string
Call `rlang::last_error()` to see a backtrace 

My guess is that by calling the fun before converting it to a string, it gets evaluated inside function and hence throw the error message. But why does this happen since I didn't do any assignments?

My questions are why does it happen and is there a better way to convert function name to string?

Any help is appreciated, thanks!

like image 873
yusuzech Avatar asked Mar 14 '26 14:03

yusuzech


2 Answers

This isn't a complete answer, but I don't think it fits in a comment.

R has a mechanism called pass-by-promise, whereby a function's formal arguments are lazy objects (promises) that only get evaluated when they are used. Even if you didn't perform any assignment, the call to is.function uses the argument, so the promise is "replaced" by the result of evaluating it.

Nevertheless, in my opinion, this seems like an inconsistency in rlang*, especially given cory's answer, which implies that R can still find the promise object even after a given parameter has been used; the mechanism to do so might not be part of R's public API though.

*EDIT: see coments.

Regardless, you could treat enexpr/enquo/ensym like base::missing, in the sense that you should only use them with parameters you haven't used at all in the function's body.

like image 190
Alexis Avatar answered Mar 17 '26 04:03

Alexis


Maybe use this instead?

func_to_string2 <- function(fun){
  is.function(fun)
  deparse(substitute(fun)) 
  #print(rlang::as_string(rlang::enexpr(fun)))
}
> func_to_string2(sum)
[1] "sum"
like image 32
cory Avatar answered Mar 17 '26 03:03

cory



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!