Why should someone use for initializing an empty object in R?
Clash Royale CLAN TAG#URR8PPP
up vote
12
down vote
favorite
It seems that some programmers are using:
a =
a$foo = 1
a$bar = 2
What is the benefit over a = list(foo = 1, bar = 2)
?
Why should be used? This expression only returns
NULL
, so a NULL
assignment would do the same, wouldn't it?
r null
add a comment |Â
up vote
12
down vote
favorite
It seems that some programmers are using:
a =
a$foo = 1
a$bar = 2
What is the benefit over a = list(foo = 1, bar = 2)
?
Why should be used? This expression only returns
NULL
, so a NULL
assignment would do the same, wouldn't it?
r null
10
it's likely a carry over from usage in other programming language. that particular GH user is a polyglot and sometimes old habits die hard.
– hrbrmstr
Sep 1 at 22:31
I only found 6 instances on SO of<-
using SymbolHound
– smci
Sep 2 at 17:47
add a comment |Â
up vote
12
down vote
favorite
up vote
12
down vote
favorite
It seems that some programmers are using:
a =
a$foo = 1
a$bar = 2
What is the benefit over a = list(foo = 1, bar = 2)
?
Why should be used? This expression only returns
NULL
, so a NULL
assignment would do the same, wouldn't it?
r null
It seems that some programmers are using:
a =
a$foo = 1
a$bar = 2
What is the benefit over a = list(foo = 1, bar = 2)
?
Why should be used? This expression only returns
NULL
, so a NULL
assignment would do the same, wouldn't it?
r null
edited Sep 2 at 21:38
smci
13.7k666100
13.7k666100
asked Sep 1 at 22:09
petres
358114
358114
10
it's likely a carry over from usage in other programming language. that particular GH user is a polyglot and sometimes old habits die hard.
– hrbrmstr
Sep 1 at 22:31
I only found 6 instances on SO of<-
using SymbolHound
– smci
Sep 2 at 17:47
add a comment |Â
10
it's likely a carry over from usage in other programming language. that particular GH user is a polyglot and sometimes old habits die hard.
– hrbrmstr
Sep 1 at 22:31
I only found 6 instances on SO of<-
using SymbolHound
– smci
Sep 2 at 17:47
10
10
it's likely a carry over from usage in other programming language. that particular GH user is a polyglot and sometimes old habits die hard.
– hrbrmstr
Sep 1 at 22:31
it's likely a carry over from usage in other programming language. that particular GH user is a polyglot and sometimes old habits die hard.
– hrbrmstr
Sep 1 at 22:31
I only found 6 instances on SO of
<-
using SymbolHound– smci
Sep 2 at 17:47
I only found 6 instances on SO of
<-
using SymbolHound– smci
Sep 2 at 17:47
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
12
down vote
accepted
Your first query
Why should
be used, this expression only returns
NULL
, so anNULL
assignment would do the same, wouldn't it?
Yes, a <- NULL
gives the same effect. Using is likely to be a personal style.
NULL
NULL
is probably the most versatile and confusing R object. From R language definition of NULL:
It is used whenever there is a need to indicate or specify that an object is absent. It should not be confused with a vector or list of zero length.
The
NULL
object has no type and no modifiable properties. There is only one NULL object in R, to which all instances refer. To test forNULL
useis.null
. You cannot set attributes onNULL
.
Strictly speaking, NULL
is just NULL
. And it is the only thing that is.null
returns TRUE
. However, according to ?NULL
:
Objects with value NULL can be changed by replacement operators and will be coerced to the type of the right-hand side.
So, while it is not identical to a length-0 vector with a legitimate mode (not all modes in R are allowed in a vector; read ?mode
for the full list of modes and ?vector
for what are legitimate for a vector), this flexible coercion often makes it behave like a length-0 vector:
## examples of atomic mode
integer(0) ## vector(mode = "integer", length = 0)
numeric(0) ## vector(mode = "numeric", length = 0)
character(0) ## vector(mode = "character", length = 0)
logical(0) ## vector(mode = "logical", length = 0)
## "list" mode
list() ## vector(mode = "list", length = 0)
## "expression" mode
expression() ## vector(mode = "expression", length = 0)
You can do vector concatenation:
c(NULL, 0L) ## c(integer(0), 0L)
c(NULL, expression(1+2)) ## c(expression(), expression(1+2))
c(NULL, list(foo = 1)) ## c(list(), list(foo = 1))
You can grow a vector (as you did in your question):
a <- NULL; a[1] <- 1; a[2] <- 2
## a <- numeric(0); a[1] <- 1; a[2] <- 2
a <- NULL; a[1] <- TRUE; a[2] <- FALSE
## a <- logical(0); a[1] <- TRUE; a[2] <- FALSE
a <- NULL; a$foo <- 1; a$bar <- 2
## a <- list(); a$foo <- 1; a$bar <- 2
a <- NULL; a[1] <- expression(1+1); a[2] <- expression(2+2)
## a <- expression(); a[1] <- expression(1+1); a[2] <- expression(2+2)
Using to generate
NULL
is similar to expression()
. Though not identical, the run-time coercion when you later do something with it really makes them indistinguishable. For example, when growing a list, any of the following would work:
a <- NULL; a$foo <- 1; a$bar <- 2
a <- numeric(0); a$foo <- 1; a$bar <- 2 ## there is a warning
a <- character(0); a$foo <- 1; a$bar <- 2 ## there is a warning
a <- expression(); a$foo <- 1; a$bar <- 2
a <- list(); a$foo <- 1; a$bar <- 2
For a length-0 vector with an atomic mode, a warning is produced during run-time coercion (because the change from "atomic" to "recursive" is too significant):
#Warning message:
#In a$foo <- 1 : Coercing LHS to a list
We don't get a warning for expression setup, because from ?expression
:
As an object of mode ‘"expression"’ is a list ...
Well, it is not a "list" in the usual sense; it is an abstract syntax tree that is list-alike.
Your second query
What is the benefit over
a = list(foo = 1, bar = 2)
?
There is no advantage in doing so. You should have already read elsewhere that growing objects is a bad practice in R. A random search on Google gives: growing objects and loop memory pre-allocation.
If you know the length of the vector as well as the value of its each element, create it directly, like a = list(foo = 1, bar = 2)
.
If you know the length of the vector but its elements' values are to be computed (say by a loop), set up a vector and do fill-in, like a <- vector("list", 2); a[[1]] <- 1; a[[2]] <- 2; names(a) <- c("foo", "bar")
.
In reply to Tjebo
I actually looked up
?mode
, but it doesn't list the possible modes. It points towards?typeof
which then points to the possible values listed in the structure TypeTable insrc/main/util.c
. I have not been able to find this file not even the folder (OSX). Any idea where to find this?
It means the source of an R distribution, which is a ".tar.gz" file on CRAN. An alternative is look up on https://github.com/wch/r-source. Either way, this is the table:
TypeTable =
"NULL", NILSXP , /* real types */
"symbol", SYMSXP ,
"pairlist", LISTSXP ,
"closure", CLOSXP ,
"environment", ENVSXP ,
"promise", PROMSXP ,
"language", LANGSXP ,
"special", SPECIALSXP ,
"builtin", BUILTINSXP ,
"char", CHARSXP ,
"logical", LGLSXP ,
"integer", INTSXP ,
"double", REALSXP , /*- "real", for R <= 0.61.x */
"complex", CPLXSXP ,
"character", STRSXP ,
"...", DOTSXP ,
"any", ANYSXP ,
"expression", EXPRSXP ,
"list", VECSXP ,
"externalptr", EXTPTRSXP ,
"bytecode", BCODESXP ,
"weakref", WEAKREFSXP ,
"raw", RAWSXP ,
"S4", S4SXP ,
/* aliases : */
"numeric", REALSXP ,
"name", SYMSXP ,
(char *)NULL, -1
;
add a comment |Â
up vote
6
down vote
Per R's documentation on braces and parentheses (type ?'{'
to read them), braces return the last expression evaluated within them.
In this case, a <-
essentially "returns" a null object, and is therefore equivalent to a <- NULL
, which establishes an empty variable that can then be treated as a list.
Incidentally, this is why it is possible to write R functions in which the function's output is returned simply by writing the name of the returned variable as the function's final statement. For example:
function(x)
y <- x * 2
return(y)
Is equivalent to:
function(x)
y <- x * 2
y
Or even:
function(x)
y <- x * 2
The final line of the function being an assignment suppresses printing of the result in the console, but the function definitely returns the expected value if it saved into a variable.
1
Thanks for the answer. I know thatreturns the last evaluated expression, that was not meant the be the question. The question was about, why would one prefer to write
instead of
NULL
. No one would writea = 1
instead ofa = 1
. Only because of saving three characters? I assume there are some drawbacks, like the parser is faster for a directNULL
assignment.
– petres
Sep 2 at 9:12
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
12
down vote
accepted
Your first query
Why should
be used, this expression only returns
NULL
, so anNULL
assignment would do the same, wouldn't it?
Yes, a <- NULL
gives the same effect. Using is likely to be a personal style.
NULL
NULL
is probably the most versatile and confusing R object. From R language definition of NULL:
It is used whenever there is a need to indicate or specify that an object is absent. It should not be confused with a vector or list of zero length.
The
NULL
object has no type and no modifiable properties. There is only one NULL object in R, to which all instances refer. To test forNULL
useis.null
. You cannot set attributes onNULL
.
Strictly speaking, NULL
is just NULL
. And it is the only thing that is.null
returns TRUE
. However, according to ?NULL
:
Objects with value NULL can be changed by replacement operators and will be coerced to the type of the right-hand side.
So, while it is not identical to a length-0 vector with a legitimate mode (not all modes in R are allowed in a vector; read ?mode
for the full list of modes and ?vector
for what are legitimate for a vector), this flexible coercion often makes it behave like a length-0 vector:
## examples of atomic mode
integer(0) ## vector(mode = "integer", length = 0)
numeric(0) ## vector(mode = "numeric", length = 0)
character(0) ## vector(mode = "character", length = 0)
logical(0) ## vector(mode = "logical", length = 0)
## "list" mode
list() ## vector(mode = "list", length = 0)
## "expression" mode
expression() ## vector(mode = "expression", length = 0)
You can do vector concatenation:
c(NULL, 0L) ## c(integer(0), 0L)
c(NULL, expression(1+2)) ## c(expression(), expression(1+2))
c(NULL, list(foo = 1)) ## c(list(), list(foo = 1))
You can grow a vector (as you did in your question):
a <- NULL; a[1] <- 1; a[2] <- 2
## a <- numeric(0); a[1] <- 1; a[2] <- 2
a <- NULL; a[1] <- TRUE; a[2] <- FALSE
## a <- logical(0); a[1] <- TRUE; a[2] <- FALSE
a <- NULL; a$foo <- 1; a$bar <- 2
## a <- list(); a$foo <- 1; a$bar <- 2
a <- NULL; a[1] <- expression(1+1); a[2] <- expression(2+2)
## a <- expression(); a[1] <- expression(1+1); a[2] <- expression(2+2)
Using to generate
NULL
is similar to expression()
. Though not identical, the run-time coercion when you later do something with it really makes them indistinguishable. For example, when growing a list, any of the following would work:
a <- NULL; a$foo <- 1; a$bar <- 2
a <- numeric(0); a$foo <- 1; a$bar <- 2 ## there is a warning
a <- character(0); a$foo <- 1; a$bar <- 2 ## there is a warning
a <- expression(); a$foo <- 1; a$bar <- 2
a <- list(); a$foo <- 1; a$bar <- 2
For a length-0 vector with an atomic mode, a warning is produced during run-time coercion (because the change from "atomic" to "recursive" is too significant):
#Warning message:
#In a$foo <- 1 : Coercing LHS to a list
We don't get a warning for expression setup, because from ?expression
:
As an object of mode ‘"expression"’ is a list ...
Well, it is not a "list" in the usual sense; it is an abstract syntax tree that is list-alike.
Your second query
What is the benefit over
a = list(foo = 1, bar = 2)
?
There is no advantage in doing so. You should have already read elsewhere that growing objects is a bad practice in R. A random search on Google gives: growing objects and loop memory pre-allocation.
If you know the length of the vector as well as the value of its each element, create it directly, like a = list(foo = 1, bar = 2)
.
If you know the length of the vector but its elements' values are to be computed (say by a loop), set up a vector and do fill-in, like a <- vector("list", 2); a[[1]] <- 1; a[[2]] <- 2; names(a) <- c("foo", "bar")
.
In reply to Tjebo
I actually looked up
?mode
, but it doesn't list the possible modes. It points towards?typeof
which then points to the possible values listed in the structure TypeTable insrc/main/util.c
. I have not been able to find this file not even the folder (OSX). Any idea where to find this?
It means the source of an R distribution, which is a ".tar.gz" file on CRAN. An alternative is look up on https://github.com/wch/r-source. Either way, this is the table:
TypeTable =
"NULL", NILSXP , /* real types */
"symbol", SYMSXP ,
"pairlist", LISTSXP ,
"closure", CLOSXP ,
"environment", ENVSXP ,
"promise", PROMSXP ,
"language", LANGSXP ,
"special", SPECIALSXP ,
"builtin", BUILTINSXP ,
"char", CHARSXP ,
"logical", LGLSXP ,
"integer", INTSXP ,
"double", REALSXP , /*- "real", for R <= 0.61.x */
"complex", CPLXSXP ,
"character", STRSXP ,
"...", DOTSXP ,
"any", ANYSXP ,
"expression", EXPRSXP ,
"list", VECSXP ,
"externalptr", EXTPTRSXP ,
"bytecode", BCODESXP ,
"weakref", WEAKREFSXP ,
"raw", RAWSXP ,
"S4", S4SXP ,
/* aliases : */
"numeric", REALSXP ,
"name", SYMSXP ,
(char *)NULL, -1
;
add a comment |Â
up vote
12
down vote
accepted
Your first query
Why should
be used, this expression only returns
NULL
, so anNULL
assignment would do the same, wouldn't it?
Yes, a <- NULL
gives the same effect. Using is likely to be a personal style.
NULL
NULL
is probably the most versatile and confusing R object. From R language definition of NULL:
It is used whenever there is a need to indicate or specify that an object is absent. It should not be confused with a vector or list of zero length.
The
NULL
object has no type and no modifiable properties. There is only one NULL object in R, to which all instances refer. To test forNULL
useis.null
. You cannot set attributes onNULL
.
Strictly speaking, NULL
is just NULL
. And it is the only thing that is.null
returns TRUE
. However, according to ?NULL
:
Objects with value NULL can be changed by replacement operators and will be coerced to the type of the right-hand side.
So, while it is not identical to a length-0 vector with a legitimate mode (not all modes in R are allowed in a vector; read ?mode
for the full list of modes and ?vector
for what are legitimate for a vector), this flexible coercion often makes it behave like a length-0 vector:
## examples of atomic mode
integer(0) ## vector(mode = "integer", length = 0)
numeric(0) ## vector(mode = "numeric", length = 0)
character(0) ## vector(mode = "character", length = 0)
logical(0) ## vector(mode = "logical", length = 0)
## "list" mode
list() ## vector(mode = "list", length = 0)
## "expression" mode
expression() ## vector(mode = "expression", length = 0)
You can do vector concatenation:
c(NULL, 0L) ## c(integer(0), 0L)
c(NULL, expression(1+2)) ## c(expression(), expression(1+2))
c(NULL, list(foo = 1)) ## c(list(), list(foo = 1))
You can grow a vector (as you did in your question):
a <- NULL; a[1] <- 1; a[2] <- 2
## a <- numeric(0); a[1] <- 1; a[2] <- 2
a <- NULL; a[1] <- TRUE; a[2] <- FALSE
## a <- logical(0); a[1] <- TRUE; a[2] <- FALSE
a <- NULL; a$foo <- 1; a$bar <- 2
## a <- list(); a$foo <- 1; a$bar <- 2
a <- NULL; a[1] <- expression(1+1); a[2] <- expression(2+2)
## a <- expression(); a[1] <- expression(1+1); a[2] <- expression(2+2)
Using to generate
NULL
is similar to expression()
. Though not identical, the run-time coercion when you later do something with it really makes them indistinguishable. For example, when growing a list, any of the following would work:
a <- NULL; a$foo <- 1; a$bar <- 2
a <- numeric(0); a$foo <- 1; a$bar <- 2 ## there is a warning
a <- character(0); a$foo <- 1; a$bar <- 2 ## there is a warning
a <- expression(); a$foo <- 1; a$bar <- 2
a <- list(); a$foo <- 1; a$bar <- 2
For a length-0 vector with an atomic mode, a warning is produced during run-time coercion (because the change from "atomic" to "recursive" is too significant):
#Warning message:
#In a$foo <- 1 : Coercing LHS to a list
We don't get a warning for expression setup, because from ?expression
:
As an object of mode ‘"expression"’ is a list ...
Well, it is not a "list" in the usual sense; it is an abstract syntax tree that is list-alike.
Your second query
What is the benefit over
a = list(foo = 1, bar = 2)
?
There is no advantage in doing so. You should have already read elsewhere that growing objects is a bad practice in R. A random search on Google gives: growing objects and loop memory pre-allocation.
If you know the length of the vector as well as the value of its each element, create it directly, like a = list(foo = 1, bar = 2)
.
If you know the length of the vector but its elements' values are to be computed (say by a loop), set up a vector and do fill-in, like a <- vector("list", 2); a[[1]] <- 1; a[[2]] <- 2; names(a) <- c("foo", "bar")
.
In reply to Tjebo
I actually looked up
?mode
, but it doesn't list the possible modes. It points towards?typeof
which then points to the possible values listed in the structure TypeTable insrc/main/util.c
. I have not been able to find this file not even the folder (OSX). Any idea where to find this?
It means the source of an R distribution, which is a ".tar.gz" file on CRAN. An alternative is look up on https://github.com/wch/r-source. Either way, this is the table:
TypeTable =
"NULL", NILSXP , /* real types */
"symbol", SYMSXP ,
"pairlist", LISTSXP ,
"closure", CLOSXP ,
"environment", ENVSXP ,
"promise", PROMSXP ,
"language", LANGSXP ,
"special", SPECIALSXP ,
"builtin", BUILTINSXP ,
"char", CHARSXP ,
"logical", LGLSXP ,
"integer", INTSXP ,
"double", REALSXP , /*- "real", for R <= 0.61.x */
"complex", CPLXSXP ,
"character", STRSXP ,
"...", DOTSXP ,
"any", ANYSXP ,
"expression", EXPRSXP ,
"list", VECSXP ,
"externalptr", EXTPTRSXP ,
"bytecode", BCODESXP ,
"weakref", WEAKREFSXP ,
"raw", RAWSXP ,
"S4", S4SXP ,
/* aliases : */
"numeric", REALSXP ,
"name", SYMSXP ,
(char *)NULL, -1
;
add a comment |Â
up vote
12
down vote
accepted
up vote
12
down vote
accepted
Your first query
Why should
be used, this expression only returns
NULL
, so anNULL
assignment would do the same, wouldn't it?
Yes, a <- NULL
gives the same effect. Using is likely to be a personal style.
NULL
NULL
is probably the most versatile and confusing R object. From R language definition of NULL:
It is used whenever there is a need to indicate or specify that an object is absent. It should not be confused with a vector or list of zero length.
The
NULL
object has no type and no modifiable properties. There is only one NULL object in R, to which all instances refer. To test forNULL
useis.null
. You cannot set attributes onNULL
.
Strictly speaking, NULL
is just NULL
. And it is the only thing that is.null
returns TRUE
. However, according to ?NULL
:
Objects with value NULL can be changed by replacement operators and will be coerced to the type of the right-hand side.
So, while it is not identical to a length-0 vector with a legitimate mode (not all modes in R are allowed in a vector; read ?mode
for the full list of modes and ?vector
for what are legitimate for a vector), this flexible coercion often makes it behave like a length-0 vector:
## examples of atomic mode
integer(0) ## vector(mode = "integer", length = 0)
numeric(0) ## vector(mode = "numeric", length = 0)
character(0) ## vector(mode = "character", length = 0)
logical(0) ## vector(mode = "logical", length = 0)
## "list" mode
list() ## vector(mode = "list", length = 0)
## "expression" mode
expression() ## vector(mode = "expression", length = 0)
You can do vector concatenation:
c(NULL, 0L) ## c(integer(0), 0L)
c(NULL, expression(1+2)) ## c(expression(), expression(1+2))
c(NULL, list(foo = 1)) ## c(list(), list(foo = 1))
You can grow a vector (as you did in your question):
a <- NULL; a[1] <- 1; a[2] <- 2
## a <- numeric(0); a[1] <- 1; a[2] <- 2
a <- NULL; a[1] <- TRUE; a[2] <- FALSE
## a <- logical(0); a[1] <- TRUE; a[2] <- FALSE
a <- NULL; a$foo <- 1; a$bar <- 2
## a <- list(); a$foo <- 1; a$bar <- 2
a <- NULL; a[1] <- expression(1+1); a[2] <- expression(2+2)
## a <- expression(); a[1] <- expression(1+1); a[2] <- expression(2+2)
Using to generate
NULL
is similar to expression()
. Though not identical, the run-time coercion when you later do something with it really makes them indistinguishable. For example, when growing a list, any of the following would work:
a <- NULL; a$foo <- 1; a$bar <- 2
a <- numeric(0); a$foo <- 1; a$bar <- 2 ## there is a warning
a <- character(0); a$foo <- 1; a$bar <- 2 ## there is a warning
a <- expression(); a$foo <- 1; a$bar <- 2
a <- list(); a$foo <- 1; a$bar <- 2
For a length-0 vector with an atomic mode, a warning is produced during run-time coercion (because the change from "atomic" to "recursive" is too significant):
#Warning message:
#In a$foo <- 1 : Coercing LHS to a list
We don't get a warning for expression setup, because from ?expression
:
As an object of mode ‘"expression"’ is a list ...
Well, it is not a "list" in the usual sense; it is an abstract syntax tree that is list-alike.
Your second query
What is the benefit over
a = list(foo = 1, bar = 2)
?
There is no advantage in doing so. You should have already read elsewhere that growing objects is a bad practice in R. A random search on Google gives: growing objects and loop memory pre-allocation.
If you know the length of the vector as well as the value of its each element, create it directly, like a = list(foo = 1, bar = 2)
.
If you know the length of the vector but its elements' values are to be computed (say by a loop), set up a vector and do fill-in, like a <- vector("list", 2); a[[1]] <- 1; a[[2]] <- 2; names(a) <- c("foo", "bar")
.
In reply to Tjebo
I actually looked up
?mode
, but it doesn't list the possible modes. It points towards?typeof
which then points to the possible values listed in the structure TypeTable insrc/main/util.c
. I have not been able to find this file not even the folder (OSX). Any idea where to find this?
It means the source of an R distribution, which is a ".tar.gz" file on CRAN. An alternative is look up on https://github.com/wch/r-source. Either way, this is the table:
TypeTable =
"NULL", NILSXP , /* real types */
"symbol", SYMSXP ,
"pairlist", LISTSXP ,
"closure", CLOSXP ,
"environment", ENVSXP ,
"promise", PROMSXP ,
"language", LANGSXP ,
"special", SPECIALSXP ,
"builtin", BUILTINSXP ,
"char", CHARSXP ,
"logical", LGLSXP ,
"integer", INTSXP ,
"double", REALSXP , /*- "real", for R <= 0.61.x */
"complex", CPLXSXP ,
"character", STRSXP ,
"...", DOTSXP ,
"any", ANYSXP ,
"expression", EXPRSXP ,
"list", VECSXP ,
"externalptr", EXTPTRSXP ,
"bytecode", BCODESXP ,
"weakref", WEAKREFSXP ,
"raw", RAWSXP ,
"S4", S4SXP ,
/* aliases : */
"numeric", REALSXP ,
"name", SYMSXP ,
(char *)NULL, -1
;
Your first query
Why should
be used, this expression only returns
NULL
, so anNULL
assignment would do the same, wouldn't it?
Yes, a <- NULL
gives the same effect. Using is likely to be a personal style.
NULL
NULL
is probably the most versatile and confusing R object. From R language definition of NULL:
It is used whenever there is a need to indicate or specify that an object is absent. It should not be confused with a vector or list of zero length.
The
NULL
object has no type and no modifiable properties. There is only one NULL object in R, to which all instances refer. To test forNULL
useis.null
. You cannot set attributes onNULL
.
Strictly speaking, NULL
is just NULL
. And it is the only thing that is.null
returns TRUE
. However, according to ?NULL
:
Objects with value NULL can be changed by replacement operators and will be coerced to the type of the right-hand side.
So, while it is not identical to a length-0 vector with a legitimate mode (not all modes in R are allowed in a vector; read ?mode
for the full list of modes and ?vector
for what are legitimate for a vector), this flexible coercion often makes it behave like a length-0 vector:
## examples of atomic mode
integer(0) ## vector(mode = "integer", length = 0)
numeric(0) ## vector(mode = "numeric", length = 0)
character(0) ## vector(mode = "character", length = 0)
logical(0) ## vector(mode = "logical", length = 0)
## "list" mode
list() ## vector(mode = "list", length = 0)
## "expression" mode
expression() ## vector(mode = "expression", length = 0)
You can do vector concatenation:
c(NULL, 0L) ## c(integer(0), 0L)
c(NULL, expression(1+2)) ## c(expression(), expression(1+2))
c(NULL, list(foo = 1)) ## c(list(), list(foo = 1))
You can grow a vector (as you did in your question):
a <- NULL; a[1] <- 1; a[2] <- 2
## a <- numeric(0); a[1] <- 1; a[2] <- 2
a <- NULL; a[1] <- TRUE; a[2] <- FALSE
## a <- logical(0); a[1] <- TRUE; a[2] <- FALSE
a <- NULL; a$foo <- 1; a$bar <- 2
## a <- list(); a$foo <- 1; a$bar <- 2
a <- NULL; a[1] <- expression(1+1); a[2] <- expression(2+2)
## a <- expression(); a[1] <- expression(1+1); a[2] <- expression(2+2)
Using to generate
NULL
is similar to expression()
. Though not identical, the run-time coercion when you later do something with it really makes them indistinguishable. For example, when growing a list, any of the following would work:
a <- NULL; a$foo <- 1; a$bar <- 2
a <- numeric(0); a$foo <- 1; a$bar <- 2 ## there is a warning
a <- character(0); a$foo <- 1; a$bar <- 2 ## there is a warning
a <- expression(); a$foo <- 1; a$bar <- 2
a <- list(); a$foo <- 1; a$bar <- 2
For a length-0 vector with an atomic mode, a warning is produced during run-time coercion (because the change from "atomic" to "recursive" is too significant):
#Warning message:
#In a$foo <- 1 : Coercing LHS to a list
We don't get a warning for expression setup, because from ?expression
:
As an object of mode ‘"expression"’ is a list ...
Well, it is not a "list" in the usual sense; it is an abstract syntax tree that is list-alike.
Your second query
What is the benefit over
a = list(foo = 1, bar = 2)
?
There is no advantage in doing so. You should have already read elsewhere that growing objects is a bad practice in R. A random search on Google gives: growing objects and loop memory pre-allocation.
If you know the length of the vector as well as the value of its each element, create it directly, like a = list(foo = 1, bar = 2)
.
If you know the length of the vector but its elements' values are to be computed (say by a loop), set up a vector and do fill-in, like a <- vector("list", 2); a[[1]] <- 1; a[[2]] <- 2; names(a) <- c("foo", "bar")
.
In reply to Tjebo
I actually looked up
?mode
, but it doesn't list the possible modes. It points towards?typeof
which then points to the possible values listed in the structure TypeTable insrc/main/util.c
. I have not been able to find this file not even the folder (OSX). Any idea where to find this?
It means the source of an R distribution, which is a ".tar.gz" file on CRAN. An alternative is look up on https://github.com/wch/r-source. Either way, this is the table:
TypeTable =
"NULL", NILSXP , /* real types */
"symbol", SYMSXP ,
"pairlist", LISTSXP ,
"closure", CLOSXP ,
"environment", ENVSXP ,
"promise", PROMSXP ,
"language", LANGSXP ,
"special", SPECIALSXP ,
"builtin", BUILTINSXP ,
"char", CHARSXP ,
"logical", LGLSXP ,
"integer", INTSXP ,
"double", REALSXP , /*- "real", for R <= 0.61.x */
"complex", CPLXSXP ,
"character", STRSXP ,
"...", DOTSXP ,
"any", ANYSXP ,
"expression", EXPRSXP ,
"list", VECSXP ,
"externalptr", EXTPTRSXP ,
"bytecode", BCODESXP ,
"weakref", WEAKREFSXP ,
"raw", RAWSXP ,
"S4", S4SXP ,
/* aliases : */
"numeric", REALSXP ,
"name", SYMSXP ,
(char *)NULL, -1
;
edited Sep 2 at 13:45
answered Sep 1 at 23:09


æÂŽå“²æºÂ
43.4k1477119
43.4k1477119
add a comment |Â
add a comment |Â
up vote
6
down vote
Per R's documentation on braces and parentheses (type ?'{'
to read them), braces return the last expression evaluated within them.
In this case, a <-
essentially "returns" a null object, and is therefore equivalent to a <- NULL
, which establishes an empty variable that can then be treated as a list.
Incidentally, this is why it is possible to write R functions in which the function's output is returned simply by writing the name of the returned variable as the function's final statement. For example:
function(x)
y <- x * 2
return(y)
Is equivalent to:
function(x)
y <- x * 2
y
Or even:
function(x)
y <- x * 2
The final line of the function being an assignment suppresses printing of the result in the console, but the function definitely returns the expected value if it saved into a variable.
1
Thanks for the answer. I know thatreturns the last evaluated expression, that was not meant the be the question. The question was about, why would one prefer to write
instead of
NULL
. No one would writea = 1
instead ofa = 1
. Only because of saving three characters? I assume there are some drawbacks, like the parser is faster for a directNULL
assignment.
– petres
Sep 2 at 9:12
add a comment |Â
up vote
6
down vote
Per R's documentation on braces and parentheses (type ?'{'
to read them), braces return the last expression evaluated within them.
In this case, a <-
essentially "returns" a null object, and is therefore equivalent to a <- NULL
, which establishes an empty variable that can then be treated as a list.
Incidentally, this is why it is possible to write R functions in which the function's output is returned simply by writing the name of the returned variable as the function's final statement. For example:
function(x)
y <- x * 2
return(y)
Is equivalent to:
function(x)
y <- x * 2
y
Or even:
function(x)
y <- x * 2
The final line of the function being an assignment suppresses printing of the result in the console, but the function definitely returns the expected value if it saved into a variable.
1
Thanks for the answer. I know thatreturns the last evaluated expression, that was not meant the be the question. The question was about, why would one prefer to write
instead of
NULL
. No one would writea = 1
instead ofa = 1
. Only because of saving three characters? I assume there are some drawbacks, like the parser is faster for a directNULL
assignment.
– petres
Sep 2 at 9:12
add a comment |Â
up vote
6
down vote
up vote
6
down vote
Per R's documentation on braces and parentheses (type ?'{'
to read them), braces return the last expression evaluated within them.
In this case, a <-
essentially "returns" a null object, and is therefore equivalent to a <- NULL
, which establishes an empty variable that can then be treated as a list.
Incidentally, this is why it is possible to write R functions in which the function's output is returned simply by writing the name of the returned variable as the function's final statement. For example:
function(x)
y <- x * 2
return(y)
Is equivalent to:
function(x)
y <- x * 2
y
Or even:
function(x)
y <- x * 2
The final line of the function being an assignment suppresses printing of the result in the console, but the function definitely returns the expected value if it saved into a variable.
Per R's documentation on braces and parentheses (type ?'{'
to read them), braces return the last expression evaluated within them.
In this case, a <-
essentially "returns" a null object, and is therefore equivalent to a <- NULL
, which establishes an empty variable that can then be treated as a list.
Incidentally, this is why it is possible to write R functions in which the function's output is returned simply by writing the name of the returned variable as the function's final statement. For example:
function(x)
y <- x * 2
return(y)
Is equivalent to:
function(x)
y <- x * 2
y
Or even:
function(x)
y <- x * 2
The final line of the function being an assignment suppresses printing of the result in the console, but the function definitely returns the expected value if it saved into a variable.
edited Sep 2 at 11:07


Tjebo
1,7591022
1,7591022
answered Sep 1 at 22:54


jdobres
3,7221522
3,7221522
1
Thanks for the answer. I know thatreturns the last evaluated expression, that was not meant the be the question. The question was about, why would one prefer to write
instead of
NULL
. No one would writea = 1
instead ofa = 1
. Only because of saving three characters? I assume there are some drawbacks, like the parser is faster for a directNULL
assignment.
– petres
Sep 2 at 9:12
add a comment |Â
1
Thanks for the answer. I know thatreturns the last evaluated expression, that was not meant the be the question. The question was about, why would one prefer to write
instead of
NULL
. No one would writea = 1
instead ofa = 1
. Only because of saving three characters? I assume there are some drawbacks, like the parser is faster for a directNULL
assignment.
– petres
Sep 2 at 9:12
1
1
Thanks for the answer. I know that
returns the last evaluated expression, that was not meant the be the question. The question was about, why would one prefer to write
instead of NULL
. No one would write a = 1
instead of a = 1
. Only because of saving three characters? I assume there are some drawbacks, like the parser is faster for a direct NULL
assignment.– petres
Sep 2 at 9:12
Thanks for the answer. I know that
returns the last evaluated expression, that was not meant the be the question. The question was about, why would one prefer to write
instead of NULL
. No one would write a = 1
instead of a = 1
. Only because of saving three characters? I assume there are some drawbacks, like the parser is faster for a direct NULL
assignment.– petres
Sep 2 at 9:12
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52132542%2fwhy-should-someone-use-for-initializing-an-empty-object-in-r%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
10
it's likely a carry over from usage in other programming language. that particular GH user is a polyglot and sometimes old habits die hard.
– hrbrmstr
Sep 1 at 22:31
I only found 6 instances on SO of
<-
using SymbolHound– smci
Sep 2 at 17:47