Skip to content
Back to formatted view

Raw Message

Message-ID: <4DBF0FE9.9010605@gmail.com>
Date: 2011-05-02T20:11:21Z
From: Duncan Murdoch
Subject: Capturing the expression representing the body of a function
In-Reply-To: <BANLkTikv5z7c-mUoNoDDsJA-_aNLWr_f+g@mail.gmail.com>

On 02/05/2011 3:21 PM, Hadley Wickham wrote:
> Hi all,
>
> What's the preferred way of capturing the expression representing the
> contents of a function?
>
> * body(write.csv) gives me a braced expression
> * body(write.csv)[-1] gives me a mangled call
> * as.list(body(write.csv)[-1]) gives me a list of calls
> * as.expression(as.list(body(write.csv)[-1])) is what I want but seems
> like too much work
>
> Any suggestions?

The body of a function isn't an expression, it's a language object.  A 
language object is represented internally as a pairlist, while an 
expression is represented as a generic vector, i.e. the thing that 
list() gives.

Your 1st try gives you the language object.

The other ones only work when the body consists of a call to `{`, as the 
body of most complex functions does, but not for simple ones like

f <- function(x) 2*x

So I would say your question should be:  "What's the best way to 
construct an expression vector s.t. evaluating its elements in order is 
like evaluating the body of a function?"

And the answer to that is something like

body2expr <- function(f) {
   body <- body(f)
   if (typeof(body) == "language" && identical(body[[1]], quote(`{`))) 
as.expression(as.list(body[-1]))
   else as.expression(body)
}

Duncan Murdoch