-
Notifications
You must be signed in to change notification settings - Fork 48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
interface around {fmt} for cpp11::stop()
and cpp11::warning()` message formatting
#209
Conversation
So I was thinking about this some this morning, and I think we will either have to use new function names (something like This is because existing packages that are using Another argument in favor of the Which way do you think would be best? |
I'd be in favor of the later! I think decreasing overhead is probably important to a lot of people using cpp11. What about you? |
yeah that is the way I was leaning, though I worry if it is only opt-in then people may not realize it is an option / never use it. |
We could try to make a ruckus about? Adding examples in documentation? Also, could we make fmt for |
inst/include/cpp11/protect.hpp
Outdated
void stop [[noreturn]] (const std::string& fmt, Args... args) { | ||
safe.noreturn(Rf_errorcall)(R_NilValue, fmt.c_str(), args...); | ||
void stop [[noreturn]] (const std::string& fmt_arg, Args... args) { | ||
std::string msg = fmt::format(fmt_arg, args...); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, it's unfortunate that we're losing the %x
format specifier for SEXP
s. This could be recoverable by introducing a helper function:
// pass through by default
template <typename T>
const T& as_formattable(const T& value) { return value; }
// specialization for SEXP:
std::string as_formattable(SEXP sexp) { return gettextf("%x", sexp); }
Used like so:
std::string msg = fmt::format(fmt_arg, args...); | |
std::string msg = fmt::format(fmt_arg, as_formattable(args)...); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you would use cpp11::stop("{0:x}", my_sexp)
, or ({0:#x}
if you want the leading 0x) to print the hexadecimal address for a sexp. (https://fmt.dev/latest/syntax.html#format-examples)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I misunderstood the purpose of %x
. I thought it gave a string representation of the pointed value rather than a representation of the pointer itself. Let me rephrase: would it be desirable to intercept SEXP
pointers and replace them with capture.output(print(value))
or so? It'd probably be better to include that as a sexp::to_string()
so that we can write
cpp11::stop("Invalid: {}", cpp11::sexp(value).to_string());
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, maybe, though it is not always clear what output would be preferred for a given SEXP, possibly something like that returned from R_inspect()
might be the most useful for any SEXP type, though the default arguments can generate a lot of data for deeply nested objects.
> .Internal(inspect(1:10))
@7ff6163c1388 13 INTSXP g0c0 [REF(65535)] 1 : 10 (compact)
Co-authored-by: Benjamin Kietzman <bengilgit@gmail.com>
LGTM, I think this can be merged once the tests are green. |
@jimhester Let me know what you think! Tests are pretty simple but we can add more if issues arise.
Fixes #169