Why should someone use for initializing an empty object in R?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
12
down vote

favorite
3












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?







share|improve this question


















  • 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














up vote
12
down vote

favorite
3












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?







share|improve this question


















  • 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












up vote
12
down vote

favorite
3









up vote
12
down vote

favorite
3






3





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?







share|improve this question














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?









share|improve this question













share|improve this question




share|improve this question








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












  • 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












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 an NULL 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 for NULL use is.null. You cannot set attributes on NULL.




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 in src/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
;





share|improve this answer





























    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.






    share|improve this answer


















    • 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










    Your Answer





    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    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






























    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 an NULL 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 for NULL use is.null. You cannot set attributes on NULL.




    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 in src/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
    ;





    share|improve this answer


























      up vote
      12
      down vote



      accepted










      Your first query




      Why should be used, this expression only returns NULL, so an NULL 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 for NULL use is.null. You cannot set attributes on NULL.




      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 in src/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
      ;





      share|improve this answer
























        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 an NULL 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 for NULL use is.null. You cannot set attributes on NULL.




        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 in src/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
        ;





        share|improve this answer














        Your first query




        Why should be used, this expression only returns NULL, so an NULL 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 for NULL use is.null. You cannot set attributes on NULL.




        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 in src/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
        ;






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Sep 2 at 13:45

























        answered Sep 1 at 23:09









        李哲源

        43.4k1477119




        43.4k1477119






















            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.






            share|improve this answer


















            • 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














            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.






            share|improve this answer


















            • 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












            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.






            share|improve this answer














            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.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            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 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












            • 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







            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

















             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            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













































































            Comments

            Popular posts from this blog

            What does second last employer means? [closed]

            List of Gilmore Girls characters

            Confectionery