I'm trying to grab the values of specific tags out of a bib file. Whenever I try and us either entry["bibtype"]
or entry[["bibtype"]]
I get an error, but entry$bibtype
works fine.
entry<-bibentry(
bibtype = "Manual",
title = "R: A Language and Environment for Statistical Computing",
author = person("R Development Core Team"),
organization = "R Foundation for Statistical Computing",
address = "Vienna, Austria",
year = 2010,
isbn = "3-900051-07-0",
url = "http://www.R-project.org/")
# the first two fail
entry["bibtype"]
entry[["bibtype"]]
entry$bibtype
foo <- list("bar" = "baz")
#all of these work
foo["bar"]
foo[["bar"]]
foo$bar
The error I'm getting is:
Error in switch(attr(paper, "bibtype"), Article = formatArticle(paper), :
EXPR must be a length 1 vector
Has anyone solved this? Anyway to coerce bibentries into accepting this?
tl;dr
"bibtype"
is not a named component in a "bibentry"
object, instead it is implemented as an attribute. The $
method for these objects has made a special case to access the attribute if it is the "thing" selected, whereas the [
and [[
methods do not have this "feature".
Using rref
as defined below
> attributes(unclass(rref)[[1]])$bibtype
[1] "Manual"
> attr(unclass(rref)[[1]], "bibtype")
[1] "Manual"
See the long version for a wider exposition
You want the attributes of the object but these do not appear accessible to the use via the usual methods, for example using the example from ?bibentry
:
## R reference
rref <- bibentry(bibtype = "Manual",
title = "R: A Language and Environment for Statistical Computing",
author = person("R Development Core Team"),
organization = "R Foundation for Statistical Computing",
address = "Vienna, Austria",
year = 2010,
isbn = "3-900051-07-0",
url = "http://www.R-project.org/")
we note the attribute "bibtype"
in the output from str()
> str(rref)
Class 'bibentry' hidden list of 1
$ :List of 7
..$ title : chr "R: A Language and Environment for Statistical Computing"
..$ author :Class 'person' hidden list of 1
.. ..$ :List of 5
.. .. ..$ given : chr "R Development Core Team"
.. .. ..$ family : NULL
.. .. ..$ role : NULL
.. .. ..$ email : NULL
.. .. ..$ comment: NULL
..$ organization: chr "R Foundation for Statistical Computing"
..$ address : chr "Vienna, Austria"
..$ year : chr "2010"
..$ isbn : chr "3-900051-07-0"
..$ url : chr "http://www.R-project.org/"
..- attr(*, "bibtype")= chr "Manual"
but we aren't able to access that attribute
> attr(rref, "bibtype")
NULL
> attr(rref[[1]], "bibtype")
NULL
The first fails because as far as R is concerned, the way objects of class "bibentry"
are implemented in R (or rather methods applied to them) attributes()
nor attr()
can see this particular attribute. The only attributes visible are:
> attributes(rref)
$class
[1] "bibentry"
> attributes(rref[1])
$class
[1] "bibentry"
If we unclass()
rref
, then we need to realise the object is a list with as many components as bibentries. In this case the rref
is a list with a single component, that is an object of class `"bibentry", which is a list of 7 components.
One naively would presume you could do this:
attr(rref[[1]], "bibtype")
which would take the first "bibentry"
object from rref
(there is only one) and look for the attributes on that. This doesn't work:
> attributes(rref[[1]])
$class
[1] "bibentry"
because of the way methods for [
and [[
are implemented for "bibentry"
objects:
> utils:::`[[.bibentry`
function (x, i)
{
rval <- unclass(x)[i]
class(rval) <- class(x)
rval
}
<bytecode: 0x1a75938>
<environment: namespace:utils>
[The single [
method is implemented exactly the same way.] This means you can do silly things like this:
> rref[[1]][[1]][[1]][[1]]
R Development Core Team (2010). _R: A Language and Environment for
Statistical Computing_. R Foundation for Statistical Computing, Vienna,
Austria. ISBN 3-900051-07-0, <URL: http://www.R-project.org/>.
which doesn't make any sense but all the [[1]]
are just referring to the same object, each time. I don't know if this is intentional or not; ?bibentry
has
Note:
The bibentry functionality is still experimental.
but it is suboptimal.
For now, you need to follow the implementation in utils:::`[.bibentry`
and unclass()
the object and then start subsetting and access the attributes:
> attributes(unclass(rref)[[1]])
$names
[1] "title" "author" "organization" "address" "year"
[6] "isbn" "url"
$bibtype
[1] "Manual"
> attributes(unclass(rref)[[1]])$bibtype
[1] "Manual"
> attr(unclass(rref)[[1]], "bibtype")
[1] "Manual"
Contrast the implementation of the utils:::`$.bibentry`
method with that for utils:::`[[.bibentry`
:
> utils:::`$.bibentry`
function (x, name)
{
is_attribute <- name %in% bibentry_attribute_names
rval <- if (is_attribute)
lapply(unclass(x), attr, name)
else lapply(unclass(x), "[[", name)
if (length(rval) == 1L)
rval <- rval[[1L]]
rval
}
<bytecode: 0x1b0fd70>
<environment: namespace:utils>
This method has specifically been designed to work with attributes. This all does seem somewhat non-standard behaviour in R. That explains why
> rref$bibtype
[1] "Manual"
works but the (naively) essentially equivalent
> str(rref[["bibtype"]])
Class 'bibentry' hidden list of 1
$ : NULL
fails because there isn't a component named "bibtype"
in the unclassed list, so that returns the NULL
component, whilst the error occurs when printing:
> foo <- rref[["bibtype"]]
> foo
Error in switch(attr(paper, "bibtype"), Article = formatArticle(paper), :
EXPR must be a length 1 vector
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With