I've been looking at R recently, but I've been habitually interested in language features. R can also manipulate the code itself, there is a system similar to Lisp macro. However, he is more like IO language, with the delay calculation + code operation, you can complete the function like Lisp macro, define the new "grammatical structure".
An example:
We implement a mechanism that can partially give a function parameter to get a new function (Corrie).
For example, we have a function like this:
F <-function (A, B, c) a
If we give only the first parameter value, we get a new function as follows:
Bind (f (1)) # = function (b, C) F (1, B, c)
In order to implement the simple point here, we use such placeholders:.,. _1,. _2 etc.
Bind (f (1,. _1,. _2)) # = = function (. _1,. _2) F (1,. _1,. _2)
implementation:
First give an implementation as follows, and then we explain.
Bind <-function (f) {parent<-parent.frame () env<-New. ENV (parent=parent) F<-Match.call () [[2]] fn<-f[[1]] Fargs<-list () Rargs<-sapply ( as. List (f[-1]), function (ARG) {if(Length (grep ("^\\. (_\\d+)? $", as. character (ARG)) >0) {eval (Substitute (fargs$a<<-NA, List (a=ARG))) ARG}Else{eval (ARG, env, ENV)}) FC<- as. Call (C (FN, Rargs)) eval (Call ("function", as. Pairlist (Fargs), FC))}
Parent <-parent.frame (); env<-new.env (parent=parent) Gets the environment when BIND is invoked, we will use him later because the non-placeholder needs to calculate the value in that environment.
R is inert in most cases. Here, if we don't use the bind parameter, they won't be counted. At the same time Match.call () can get the entire function call syntax tree. If we modify the syntax tree of a function call to accomplish something else, it is actually the function of "macro". One place that differs from Lisp is that we don't need to differentiate between the valuations phase (evaluate phase), and lazy valuations give us the opportunity to modify the syntax tree.
fn <-F[[1]] Gets the function name of BIND.
Rargs <-sapply (... Check if it is a placeholder and add it to the form parameter of the new function, if not calculate the value.
The last two lines generate a new function.
Test:
F <-1<-bind (f (b=., c=._2, a=a)) x (. =1)
A better example of this is https://github.com/smbache/magrittr, He realized a%>%, actually completed the above bind mechanism.
"Macros" in the R language