Quosure Tutorial


#1

I’ve added another tutorial. This one is about the structure of a quosure.

http://r.danal.com/tutorials/QuosureTree.html

It is some supporting information for the next tutorial I am working on about using quosures to program on the language.


#2
  • node_car() and node_cdr() are /very/ low level accessors that can easily make R crash. They are for experts only and mostly provided as a way of prototyping C code in R. I think you should mention the risks to the readers of your blog.

  • It is preferable to use accessors like get_expr() and get_env() to access the components of quosures. They are currently implemented as formulas but might not be in the future. Accessing the expression with f_rhs() will be soft-deprecated in the next version.


#3

Good to know f_rhs is being deprecated. I had wondered why f_rhs and get_expr returned the same thing. I’ll switch to get_expr in the next tutorial and explain why. BTW I used f_rhs because it fits in the story better given that a quosure is a one sided formula.

I think I can do some of the things I want to do with lang_head and lang_tail but I don’t know of a way to modify an expression without mut_nod_car and friends, is there one?. But I was going to put a warning on the node_ and mut_ functions in the next tutorial on these anyhow… they can do a great job of crashing a session.

How do you know when a function is scheduled for deprecation? The doc’s don’t seem to be kept up to date with that kind of info.

Thanks @lionel for the info


#4

This will be indicated in the NEWS. Note that it’s not f_rhs() as a whole that will be deprecated, it will continue to work for regular formulas.

Just extract the expression from the quosure with get_expr() and modify that expression the usual way (e.g. with the subset-assign operators). When the new expression is ready use set_expr() to update the quosure or use new_quosure() to create a new one (in which case don’t forget to supply the environment where the symbols mentioned in the expression are defined).


#5

Ahh, I didn’ t know about the NEWS file in github, thanks. But the current one doesn’t mention anything about f_rhs. Maybe it’s implied by some of the notes in it.

I’ll have to try out get_/set_ expr. If I understand things correctly I can see how lang_tail/head get_/set_expr can replace the node_ and mut_ functions.


#6

I wouldn’t use lang_head() and lang_tail() at all. While they are safer than node_car() and node_cdr(), they are unnecessarily low level for most R metaprogramming work. As for f_rhs() new behaviour it is not mentioned in the NEWS yet because it’s not been (soft-)deprecated yet.


#7

But without lang_head/tail how do you traverse (i.e. parse) the trees in the expression in the quosure?. The only alternative I see is to parse the raw text of the expression which isn’t really possible.

For example if I want to know the operator the expression uses?


#8

You use subsetting operators.


#9

The subsetting ops do a nice job of parsing out the expression so I can see their use when metaprogamming is just analyzing an expression and then goes and builds a new one or just executes some code based on the analysis.

But I don’t see how, even with set_expr, you can modify an existing expression, for example change the + in the expression 1 + 2 to a -. It seems like mut_node_ and friends are the only way to do that.

Also the strings you get with get_expr and subsetting are not formatted all that nicely and need some addition processing to make the expression look like the expression.

But maybe I am missing something here so I’ll do a bit more digging.


#10

Now that I’ve dug into parsing an expression by subsetting I can see that it works. It does produce a different object model that parsing by traversing node/car/cdr but that’s not a problem.

In the end it’s less work to parse with subset than node/car/cdr.

Edited… it’s easy to make mod’s deep in the hierarcy

I had seen the use of subsetting mentioned in the doc’s a number of times but I didn’t really grasp how to used until you mentioned it.

So it looks like I can do everything I want without having to use node_ or mut_node functions.

Thanks @lionel for your comments.


#11

Now try call[-1] <- lapply(call[-1], my_recursive_function).


#12

Thanks for the tutorial! I have a couple questions.

It sounds like a quosure should be thought of as a wrapper for an R expression. What is the motivation for using this wrapper? (Maybe you are planning to address this in your next tutorial.)

When you say that a quosure mimics the behavior of other types of R objects (such as a formula), is this the same as saying that the quosure class inherits the behavior of the formula class? If not, what is the difference between mimicking and inheritance?


#13

Hi danr, thanks for the tutorial! Do you use twitter? If yes, what’s your handle? I’d like to follow you to get blog updates.


#14

The is a new tutorial coming out shortly that covers that and more


#15

my twitter handle is @d114