How do I call the `function` function?












22















I am trying to call the function `function` to define a function in R code.



As we all know™️, `function`is a .Primitive that’s used internally by R to define functions when the user uses the conventional syntax, i.e.



mean1 = function (x, ...) base::mean(x, ...)


But there’s nothing preventing me from calling that primitive directly. Or so I thought. I can call other primitives directly (and even redefine them; for instance, in a moment of madness I overrode R’s builtin `for`). So this is in principle possible.



Yet I cannot get it to work for `function`. Here’s what I tried:



# Works
mean2 = as.function(c(formals(mean), quote(mean(x, ...))))

# Works
mean3 = eval(call('function', formals(mean), quote(mean(x, ...))))

# Error: invalid formal argument list for "function"
mean4 = `function`(formals(mean), quote(mean(x, ...)))


The fact that mean3 in particular works indicates to me that mean4 should work. But it doesn’t. Why?



I checked the definition of the `function` primitive in the R source. do_function is defined in eval.c. And I see that it calls CheckFormals, which ensures that each argument is a symbol, and this fails. But why does it check this, and what does that mean?



And most importantly: Is there a way of calling the `function` primitive directly?





Just to clarify: There are trivial workarounds (this question lists two, and there’s at least a third). But I’d like to understand how this (does not) works.










share|improve this question























  • Duplicate of stackoverflow.com/q/53218422/1968 (I swear I found this afterwards)

    – Konrad Rudolph
    Feb 8 at 18:04











  • Related: stackoverflow.com/questions/12982528/…

    – Artem Sokolov
    Feb 8 at 18:06











  • @Moody's answer in the link above points out rlang::new_function, which can be called directly as a function and does essentially what function does.

    – Artem Sokolov
    Feb 8 at 18:08











  • @ArtemSokolov … sure but that does exactly what my mean3 definition does. I’m well aware of workarounds, I was just curious why it doesn’t seem to work.

    – Konrad Rudolph
    Feb 8 at 18:15













  • Sorry for misunderstanding. Please see my answer below.

    – Artem Sokolov
    Feb 8 at 22:02
















22















I am trying to call the function `function` to define a function in R code.



As we all know™️, `function`is a .Primitive that’s used internally by R to define functions when the user uses the conventional syntax, i.e.



mean1 = function (x, ...) base::mean(x, ...)


But there’s nothing preventing me from calling that primitive directly. Or so I thought. I can call other primitives directly (and even redefine them; for instance, in a moment of madness I overrode R’s builtin `for`). So this is in principle possible.



Yet I cannot get it to work for `function`. Here’s what I tried:



# Works
mean2 = as.function(c(formals(mean), quote(mean(x, ...))))

# Works
mean3 = eval(call('function', formals(mean), quote(mean(x, ...))))

# Error: invalid formal argument list for "function"
mean4 = `function`(formals(mean), quote(mean(x, ...)))


The fact that mean3 in particular works indicates to me that mean4 should work. But it doesn’t. Why?



I checked the definition of the `function` primitive in the R source. do_function is defined in eval.c. And I see that it calls CheckFormals, which ensures that each argument is a symbol, and this fails. But why does it check this, and what does that mean?



And most importantly: Is there a way of calling the `function` primitive directly?





Just to clarify: There are trivial workarounds (this question lists two, and there’s at least a third). But I’d like to understand how this (does not) works.










share|improve this question























  • Duplicate of stackoverflow.com/q/53218422/1968 (I swear I found this afterwards)

    – Konrad Rudolph
    Feb 8 at 18:04











  • Related: stackoverflow.com/questions/12982528/…

    – Artem Sokolov
    Feb 8 at 18:06











  • @Moody's answer in the link above points out rlang::new_function, which can be called directly as a function and does essentially what function does.

    – Artem Sokolov
    Feb 8 at 18:08











  • @ArtemSokolov … sure but that does exactly what my mean3 definition does. I’m well aware of workarounds, I was just curious why it doesn’t seem to work.

    – Konrad Rudolph
    Feb 8 at 18:15













  • Sorry for misunderstanding. Please see my answer below.

    – Artem Sokolov
    Feb 8 at 22:02














22












22








22


5






I am trying to call the function `function` to define a function in R code.



As we all know™️, `function`is a .Primitive that’s used internally by R to define functions when the user uses the conventional syntax, i.e.



mean1 = function (x, ...) base::mean(x, ...)


But there’s nothing preventing me from calling that primitive directly. Or so I thought. I can call other primitives directly (and even redefine them; for instance, in a moment of madness I overrode R’s builtin `for`). So this is in principle possible.



Yet I cannot get it to work for `function`. Here’s what I tried:



# Works
mean2 = as.function(c(formals(mean), quote(mean(x, ...))))

# Works
mean3 = eval(call('function', formals(mean), quote(mean(x, ...))))

# Error: invalid formal argument list for "function"
mean4 = `function`(formals(mean), quote(mean(x, ...)))


The fact that mean3 in particular works indicates to me that mean4 should work. But it doesn’t. Why?



I checked the definition of the `function` primitive in the R source. do_function is defined in eval.c. And I see that it calls CheckFormals, which ensures that each argument is a symbol, and this fails. But why does it check this, and what does that mean?



And most importantly: Is there a way of calling the `function` primitive directly?





Just to clarify: There are trivial workarounds (this question lists two, and there’s at least a third). But I’d like to understand how this (does not) works.










share|improve this question














I am trying to call the function `function` to define a function in R code.



As we all know™️, `function`is a .Primitive that’s used internally by R to define functions when the user uses the conventional syntax, i.e.



mean1 = function (x, ...) base::mean(x, ...)


But there’s nothing preventing me from calling that primitive directly. Or so I thought. I can call other primitives directly (and even redefine them; for instance, in a moment of madness I overrode R’s builtin `for`). So this is in principle possible.



Yet I cannot get it to work for `function`. Here’s what I tried:



# Works
mean2 = as.function(c(formals(mean), quote(mean(x, ...))))

# Works
mean3 = eval(call('function', formals(mean), quote(mean(x, ...))))

# Error: invalid formal argument list for "function"
mean4 = `function`(formals(mean), quote(mean(x, ...)))


The fact that mean3 in particular works indicates to me that mean4 should work. But it doesn’t. Why?



I checked the definition of the `function` primitive in the R source. do_function is defined in eval.c. And I see that it calls CheckFormals, which ensures that each argument is a symbol, and this fails. But why does it check this, and what does that mean?



And most importantly: Is there a way of calling the `function` primitive directly?





Just to clarify: There are trivial workarounds (this question lists two, and there’s at least a third). But I’d like to understand how this (does not) works.







r






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Feb 8 at 16:39









Konrad RudolphKonrad Rudolph

400k1017881037




400k1017881037













  • Duplicate of stackoverflow.com/q/53218422/1968 (I swear I found this afterwards)

    – Konrad Rudolph
    Feb 8 at 18:04











  • Related: stackoverflow.com/questions/12982528/…

    – Artem Sokolov
    Feb 8 at 18:06











  • @Moody's answer in the link above points out rlang::new_function, which can be called directly as a function and does essentially what function does.

    – Artem Sokolov
    Feb 8 at 18:08











  • @ArtemSokolov … sure but that does exactly what my mean3 definition does. I’m well aware of workarounds, I was just curious why it doesn’t seem to work.

    – Konrad Rudolph
    Feb 8 at 18:15













  • Sorry for misunderstanding. Please see my answer below.

    – Artem Sokolov
    Feb 8 at 22:02



















  • Duplicate of stackoverflow.com/q/53218422/1968 (I swear I found this afterwards)

    – Konrad Rudolph
    Feb 8 at 18:04











  • Related: stackoverflow.com/questions/12982528/…

    – Artem Sokolov
    Feb 8 at 18:06











  • @Moody's answer in the link above points out rlang::new_function, which can be called directly as a function and does essentially what function does.

    – Artem Sokolov
    Feb 8 at 18:08











  • @ArtemSokolov … sure but that does exactly what my mean3 definition does. I’m well aware of workarounds, I was just curious why it doesn’t seem to work.

    – Konrad Rudolph
    Feb 8 at 18:15













  • Sorry for misunderstanding. Please see my answer below.

    – Artem Sokolov
    Feb 8 at 22:02

















Duplicate of stackoverflow.com/q/53218422/1968 (I swear I found this afterwards)

– Konrad Rudolph
Feb 8 at 18:04





Duplicate of stackoverflow.com/q/53218422/1968 (I swear I found this afterwards)

– Konrad Rudolph
Feb 8 at 18:04













Related: stackoverflow.com/questions/12982528/…

– Artem Sokolov
Feb 8 at 18:06





Related: stackoverflow.com/questions/12982528/…

– Artem Sokolov
Feb 8 at 18:06













@Moody's answer in the link above points out rlang::new_function, which can be called directly as a function and does essentially what function does.

– Artem Sokolov
Feb 8 at 18:08





@Moody's answer in the link above points out rlang::new_function, which can be called directly as a function and does essentially what function does.

– Artem Sokolov
Feb 8 at 18:08













@ArtemSokolov … sure but that does exactly what my mean3 definition does. I’m well aware of workarounds, I was just curious why it doesn’t seem to work.

– Konrad Rudolph
Feb 8 at 18:15







@ArtemSokolov … sure but that does exactly what my mean3 definition does. I’m well aware of workarounds, I was just curious why it doesn’t seem to work.

– Konrad Rudolph
Feb 8 at 18:15















Sorry for misunderstanding. Please see my answer below.

– Artem Sokolov
Feb 8 at 22:02





Sorry for misunderstanding. Please see my answer below.

– Artem Sokolov
Feb 8 at 22:02












3 Answers
3






active

oldest

votes


















11














This is because function is a special primitive:



typeof(`function`)
#> [1] "special"


The arguments are not evaluated, so you have actually passed quote(formals(mean)) instead of the value of formals(mean). I don't think there's a way of calling function directly without evaluation tricks, except with an empty formals list which is just NULL.






share|improve this answer



















  • 1





    I actually tried quoting the formals (as well as using alist), yet as you noticed this also doesn’t work. typeof(`for`) is also “special”, but calling ` for ` manually works.

    – Konrad Rudolph
    Feb 8 at 17:54








  • 3





    Yeah because for takes a symbol and two expressions, for which there is parser syntax. There is no explicit parser syntax for creating a pairlist literal, which is what function() takes.

    – lionel
    Feb 8 at 17:59











  • Indeed. I just figured out that you can call it with a manually generated pairlist — but once again only indirectly because, as you said, there’s no pairlist literal syntax.

    – Konrad Rudolph
    Feb 8 at 18:01





















4














For completeness’ sake, lionel’s answer hints at a way of calling `function` after all. Unfortunately it’s rather restricted, since we cannot pass any argument definition except for NULL:



mean5 = `function`(NULL, mean(x, ...))
formals(mean5) = formals(mean)


(Note the lack of quoting around the body!)



This is of course utterly unpractical (and formals<- internally calls as.function anyway.)






share|improve this answer































    2














    After digging a little bit through the source code, here are a few observations:




    1. The actual function creation is done by mkCLOSXP(). This is what gets called by function() {}, by as.function.default() and by .Primitive("function") (a.k.a. `function`)


    2. as.function.default() gets routed to do_asfunction(), which also calls CheckFormals(). However, it directly constructs these formals a few lines above that.


    3. As you pointed out, the other place where CheckFormals() gets called is inside do_function(). However, I don't think do_function() gets called by anything other than .Primitive("function"), so this is the only situation where CheckFormals() is called on the user's input.


    4. CheckFormals() does actually correctly validate a pairlist object.



    You can check the last point yourself by running parts of the CheckFormals() function using inline::cfunction



    inline::cfunction( c(x="ANY"),
    'Rprintf("is list?: %d\nTag1 OK?: %d\nTag2 OK?: %d\nTag3 NULL?: %d\n",
    isList(x), TYPEOF(TAG(x)) == SYMSXP, TYPEOF(TAG(CDR(x))) == SYMSXP,
    CDR(CDR(x)) == R_NilValue); return R_NilValue;' )( formals(mean) )

    # is list?: 1
    # Tag1 OK?: 1
    # Tag2 OK?: 1
    # Tag3 NULL?: 1


    So, somewhere between you passing formals(means) to .Primitive("function") and it getting forwarded to CheckFormals() by do_function(), the argument loses its validity. (I don't know the R source well enough to tell you how that happens.) However, since do_function() is only called by .Primitive("function"), you don't encounter this situation with any other examples.






    share|improve this answer



















    • 1





      You’re spot on as far as your reasoning goes. I think the missing piece to the puzzle is the declaration of function in names.c: Unlike your own C function, do_function doesn’t get called with the evaluated argument; instead, it gets called with unevaluated arguments, so what gets passed isn’t a pairlist, it’s a quoted expression that would evaluate to a pairlist.

      – Konrad Rudolph
      Feb 9 at 10:07











    • @KonradRudolph: Do you think this is intended behavior? Neither do_function, nor `function`, nor .Primitive("function") get used internally (as determined by grep-ing the source). So, if a user can't call it directly, who is the function meant for?

      – Artem Sokolov
      Feb 9 at 16:53








    • 2





      The function .Primitive("function") is called when you evaluate a call to function created by the parser into a function object created by the interpreter. Note that those two kinds of objects print identically, which can be confusing. Check the differences between quote(function(foo, bar) NULL) and the unquoted version. You can also verify with .Internal(inspect(quote(function(foo, bar) NULL))) that the parser correctly creates the formals list in calls to function.

      – lionel
      Feb 10 at 10:24











    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',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    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%2f54596743%2fhow-do-i-call-the-function-function%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    11














    This is because function is a special primitive:



    typeof(`function`)
    #> [1] "special"


    The arguments are not evaluated, so you have actually passed quote(formals(mean)) instead of the value of formals(mean). I don't think there's a way of calling function directly without evaluation tricks, except with an empty formals list which is just NULL.






    share|improve this answer



















    • 1





      I actually tried quoting the formals (as well as using alist), yet as you noticed this also doesn’t work. typeof(`for`) is also “special”, but calling ` for ` manually works.

      – Konrad Rudolph
      Feb 8 at 17:54








    • 3





      Yeah because for takes a symbol and two expressions, for which there is parser syntax. There is no explicit parser syntax for creating a pairlist literal, which is what function() takes.

      – lionel
      Feb 8 at 17:59











    • Indeed. I just figured out that you can call it with a manually generated pairlist — but once again only indirectly because, as you said, there’s no pairlist literal syntax.

      – Konrad Rudolph
      Feb 8 at 18:01


















    11














    This is because function is a special primitive:



    typeof(`function`)
    #> [1] "special"


    The arguments are not evaluated, so you have actually passed quote(formals(mean)) instead of the value of formals(mean). I don't think there's a way of calling function directly without evaluation tricks, except with an empty formals list which is just NULL.






    share|improve this answer



















    • 1





      I actually tried quoting the formals (as well as using alist), yet as you noticed this also doesn’t work. typeof(`for`) is also “special”, but calling ` for ` manually works.

      – Konrad Rudolph
      Feb 8 at 17:54








    • 3





      Yeah because for takes a symbol and two expressions, for which there is parser syntax. There is no explicit parser syntax for creating a pairlist literal, which is what function() takes.

      – lionel
      Feb 8 at 17:59











    • Indeed. I just figured out that you can call it with a manually generated pairlist — but once again only indirectly because, as you said, there’s no pairlist literal syntax.

      – Konrad Rudolph
      Feb 8 at 18:01
















    11












    11








    11







    This is because function is a special primitive:



    typeof(`function`)
    #> [1] "special"


    The arguments are not evaluated, so you have actually passed quote(formals(mean)) instead of the value of formals(mean). I don't think there's a way of calling function directly without evaluation tricks, except with an empty formals list which is just NULL.






    share|improve this answer













    This is because function is a special primitive:



    typeof(`function`)
    #> [1] "special"


    The arguments are not evaluated, so you have actually passed quote(formals(mean)) instead of the value of formals(mean). I don't think there's a way of calling function directly without evaluation tricks, except with an empty formals list which is just NULL.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Feb 8 at 17:53









    lionellionel

    3,0871721




    3,0871721








    • 1





      I actually tried quoting the formals (as well as using alist), yet as you noticed this also doesn’t work. typeof(`for`) is also “special”, but calling ` for ` manually works.

      – Konrad Rudolph
      Feb 8 at 17:54








    • 3





      Yeah because for takes a symbol and two expressions, for which there is parser syntax. There is no explicit parser syntax for creating a pairlist literal, which is what function() takes.

      – lionel
      Feb 8 at 17:59











    • Indeed. I just figured out that you can call it with a manually generated pairlist — but once again only indirectly because, as you said, there’s no pairlist literal syntax.

      – Konrad Rudolph
      Feb 8 at 18:01
















    • 1





      I actually tried quoting the formals (as well as using alist), yet as you noticed this also doesn’t work. typeof(`for`) is also “special”, but calling ` for ` manually works.

      – Konrad Rudolph
      Feb 8 at 17:54








    • 3





      Yeah because for takes a symbol and two expressions, for which there is parser syntax. There is no explicit parser syntax for creating a pairlist literal, which is what function() takes.

      – lionel
      Feb 8 at 17:59











    • Indeed. I just figured out that you can call it with a manually generated pairlist — but once again only indirectly because, as you said, there’s no pairlist literal syntax.

      – Konrad Rudolph
      Feb 8 at 18:01










    1




    1





    I actually tried quoting the formals (as well as using alist), yet as you noticed this also doesn’t work. typeof(`for`) is also “special”, but calling ` for ` manually works.

    – Konrad Rudolph
    Feb 8 at 17:54







    I actually tried quoting the formals (as well as using alist), yet as you noticed this also doesn’t work. typeof(`for`) is also “special”, but calling ` for ` manually works.

    – Konrad Rudolph
    Feb 8 at 17:54






    3




    3





    Yeah because for takes a symbol and two expressions, for which there is parser syntax. There is no explicit parser syntax for creating a pairlist literal, which is what function() takes.

    – lionel
    Feb 8 at 17:59





    Yeah because for takes a symbol and two expressions, for which there is parser syntax. There is no explicit parser syntax for creating a pairlist literal, which is what function() takes.

    – lionel
    Feb 8 at 17:59













    Indeed. I just figured out that you can call it with a manually generated pairlist — but once again only indirectly because, as you said, there’s no pairlist literal syntax.

    – Konrad Rudolph
    Feb 8 at 18:01







    Indeed. I just figured out that you can call it with a manually generated pairlist — but once again only indirectly because, as you said, there’s no pairlist literal syntax.

    – Konrad Rudolph
    Feb 8 at 18:01















    4














    For completeness’ sake, lionel’s answer hints at a way of calling `function` after all. Unfortunately it’s rather restricted, since we cannot pass any argument definition except for NULL:



    mean5 = `function`(NULL, mean(x, ...))
    formals(mean5) = formals(mean)


    (Note the lack of quoting around the body!)



    This is of course utterly unpractical (and formals<- internally calls as.function anyway.)






    share|improve this answer




























      4














      For completeness’ sake, lionel’s answer hints at a way of calling `function` after all. Unfortunately it’s rather restricted, since we cannot pass any argument definition except for NULL:



      mean5 = `function`(NULL, mean(x, ...))
      formals(mean5) = formals(mean)


      (Note the lack of quoting around the body!)



      This is of course utterly unpractical (and formals<- internally calls as.function anyway.)






      share|improve this answer


























        4












        4








        4







        For completeness’ sake, lionel’s answer hints at a way of calling `function` after all. Unfortunately it’s rather restricted, since we cannot pass any argument definition except for NULL:



        mean5 = `function`(NULL, mean(x, ...))
        formals(mean5) = formals(mean)


        (Note the lack of quoting around the body!)



        This is of course utterly unpractical (and formals<- internally calls as.function anyway.)






        share|improve this answer













        For completeness’ sake, lionel’s answer hints at a way of calling `function` after all. Unfortunately it’s rather restricted, since we cannot pass any argument definition except for NULL:



        mean5 = `function`(NULL, mean(x, ...))
        formals(mean5) = formals(mean)


        (Note the lack of quoting around the body!)



        This is of course utterly unpractical (and formals<- internally calls as.function anyway.)







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Feb 8 at 18:12









        Konrad RudolphKonrad Rudolph

        400k1017881037




        400k1017881037























            2














            After digging a little bit through the source code, here are a few observations:




            1. The actual function creation is done by mkCLOSXP(). This is what gets called by function() {}, by as.function.default() and by .Primitive("function") (a.k.a. `function`)


            2. as.function.default() gets routed to do_asfunction(), which also calls CheckFormals(). However, it directly constructs these formals a few lines above that.


            3. As you pointed out, the other place where CheckFormals() gets called is inside do_function(). However, I don't think do_function() gets called by anything other than .Primitive("function"), so this is the only situation where CheckFormals() is called on the user's input.


            4. CheckFormals() does actually correctly validate a pairlist object.



            You can check the last point yourself by running parts of the CheckFormals() function using inline::cfunction



            inline::cfunction( c(x="ANY"),
            'Rprintf("is list?: %d\nTag1 OK?: %d\nTag2 OK?: %d\nTag3 NULL?: %d\n",
            isList(x), TYPEOF(TAG(x)) == SYMSXP, TYPEOF(TAG(CDR(x))) == SYMSXP,
            CDR(CDR(x)) == R_NilValue); return R_NilValue;' )( formals(mean) )

            # is list?: 1
            # Tag1 OK?: 1
            # Tag2 OK?: 1
            # Tag3 NULL?: 1


            So, somewhere between you passing formals(means) to .Primitive("function") and it getting forwarded to CheckFormals() by do_function(), the argument loses its validity. (I don't know the R source well enough to tell you how that happens.) However, since do_function() is only called by .Primitive("function"), you don't encounter this situation with any other examples.






            share|improve this answer



















            • 1





              You’re spot on as far as your reasoning goes. I think the missing piece to the puzzle is the declaration of function in names.c: Unlike your own C function, do_function doesn’t get called with the evaluated argument; instead, it gets called with unevaluated arguments, so what gets passed isn’t a pairlist, it’s a quoted expression that would evaluate to a pairlist.

              – Konrad Rudolph
              Feb 9 at 10:07











            • @KonradRudolph: Do you think this is intended behavior? Neither do_function, nor `function`, nor .Primitive("function") get used internally (as determined by grep-ing the source). So, if a user can't call it directly, who is the function meant for?

              – Artem Sokolov
              Feb 9 at 16:53








            • 2





              The function .Primitive("function") is called when you evaluate a call to function created by the parser into a function object created by the interpreter. Note that those two kinds of objects print identically, which can be confusing. Check the differences between quote(function(foo, bar) NULL) and the unquoted version. You can also verify with .Internal(inspect(quote(function(foo, bar) NULL))) that the parser correctly creates the formals list in calls to function.

              – lionel
              Feb 10 at 10:24
















            2














            After digging a little bit through the source code, here are a few observations:




            1. The actual function creation is done by mkCLOSXP(). This is what gets called by function() {}, by as.function.default() and by .Primitive("function") (a.k.a. `function`)


            2. as.function.default() gets routed to do_asfunction(), which also calls CheckFormals(). However, it directly constructs these formals a few lines above that.


            3. As you pointed out, the other place where CheckFormals() gets called is inside do_function(). However, I don't think do_function() gets called by anything other than .Primitive("function"), so this is the only situation where CheckFormals() is called on the user's input.


            4. CheckFormals() does actually correctly validate a pairlist object.



            You can check the last point yourself by running parts of the CheckFormals() function using inline::cfunction



            inline::cfunction( c(x="ANY"),
            'Rprintf("is list?: %d\nTag1 OK?: %d\nTag2 OK?: %d\nTag3 NULL?: %d\n",
            isList(x), TYPEOF(TAG(x)) == SYMSXP, TYPEOF(TAG(CDR(x))) == SYMSXP,
            CDR(CDR(x)) == R_NilValue); return R_NilValue;' )( formals(mean) )

            # is list?: 1
            # Tag1 OK?: 1
            # Tag2 OK?: 1
            # Tag3 NULL?: 1


            So, somewhere between you passing formals(means) to .Primitive("function") and it getting forwarded to CheckFormals() by do_function(), the argument loses its validity. (I don't know the R source well enough to tell you how that happens.) However, since do_function() is only called by .Primitive("function"), you don't encounter this situation with any other examples.






            share|improve this answer



















            • 1





              You’re spot on as far as your reasoning goes. I think the missing piece to the puzzle is the declaration of function in names.c: Unlike your own C function, do_function doesn’t get called with the evaluated argument; instead, it gets called with unevaluated arguments, so what gets passed isn’t a pairlist, it’s a quoted expression that would evaluate to a pairlist.

              – Konrad Rudolph
              Feb 9 at 10:07











            • @KonradRudolph: Do you think this is intended behavior? Neither do_function, nor `function`, nor .Primitive("function") get used internally (as determined by grep-ing the source). So, if a user can't call it directly, who is the function meant for?

              – Artem Sokolov
              Feb 9 at 16:53








            • 2





              The function .Primitive("function") is called when you evaluate a call to function created by the parser into a function object created by the interpreter. Note that those two kinds of objects print identically, which can be confusing. Check the differences between quote(function(foo, bar) NULL) and the unquoted version. You can also verify with .Internal(inspect(quote(function(foo, bar) NULL))) that the parser correctly creates the formals list in calls to function.

              – lionel
              Feb 10 at 10:24














            2












            2








            2







            After digging a little bit through the source code, here are a few observations:




            1. The actual function creation is done by mkCLOSXP(). This is what gets called by function() {}, by as.function.default() and by .Primitive("function") (a.k.a. `function`)


            2. as.function.default() gets routed to do_asfunction(), which also calls CheckFormals(). However, it directly constructs these formals a few lines above that.


            3. As you pointed out, the other place where CheckFormals() gets called is inside do_function(). However, I don't think do_function() gets called by anything other than .Primitive("function"), so this is the only situation where CheckFormals() is called on the user's input.


            4. CheckFormals() does actually correctly validate a pairlist object.



            You can check the last point yourself by running parts of the CheckFormals() function using inline::cfunction



            inline::cfunction( c(x="ANY"),
            'Rprintf("is list?: %d\nTag1 OK?: %d\nTag2 OK?: %d\nTag3 NULL?: %d\n",
            isList(x), TYPEOF(TAG(x)) == SYMSXP, TYPEOF(TAG(CDR(x))) == SYMSXP,
            CDR(CDR(x)) == R_NilValue); return R_NilValue;' )( formals(mean) )

            # is list?: 1
            # Tag1 OK?: 1
            # Tag2 OK?: 1
            # Tag3 NULL?: 1


            So, somewhere between you passing formals(means) to .Primitive("function") and it getting forwarded to CheckFormals() by do_function(), the argument loses its validity. (I don't know the R source well enough to tell you how that happens.) However, since do_function() is only called by .Primitive("function"), you don't encounter this situation with any other examples.






            share|improve this answer













            After digging a little bit through the source code, here are a few observations:




            1. The actual function creation is done by mkCLOSXP(). This is what gets called by function() {}, by as.function.default() and by .Primitive("function") (a.k.a. `function`)


            2. as.function.default() gets routed to do_asfunction(), which also calls CheckFormals(). However, it directly constructs these formals a few lines above that.


            3. As you pointed out, the other place where CheckFormals() gets called is inside do_function(). However, I don't think do_function() gets called by anything other than .Primitive("function"), so this is the only situation where CheckFormals() is called on the user's input.


            4. CheckFormals() does actually correctly validate a pairlist object.



            You can check the last point yourself by running parts of the CheckFormals() function using inline::cfunction



            inline::cfunction( c(x="ANY"),
            'Rprintf("is list?: %d\nTag1 OK?: %d\nTag2 OK?: %d\nTag3 NULL?: %d\n",
            isList(x), TYPEOF(TAG(x)) == SYMSXP, TYPEOF(TAG(CDR(x))) == SYMSXP,
            CDR(CDR(x)) == R_NilValue); return R_NilValue;' )( formals(mean) )

            # is list?: 1
            # Tag1 OK?: 1
            # Tag2 OK?: 1
            # Tag3 NULL?: 1


            So, somewhere between you passing formals(means) to .Primitive("function") and it getting forwarded to CheckFormals() by do_function(), the argument loses its validity. (I don't know the R source well enough to tell you how that happens.) However, since do_function() is only called by .Primitive("function"), you don't encounter this situation with any other examples.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Feb 8 at 22:01









            Artem SokolovArtem Sokolov

            5,03222239




            5,03222239








            • 1





              You’re spot on as far as your reasoning goes. I think the missing piece to the puzzle is the declaration of function in names.c: Unlike your own C function, do_function doesn’t get called with the evaluated argument; instead, it gets called with unevaluated arguments, so what gets passed isn’t a pairlist, it’s a quoted expression that would evaluate to a pairlist.

              – Konrad Rudolph
              Feb 9 at 10:07











            • @KonradRudolph: Do you think this is intended behavior? Neither do_function, nor `function`, nor .Primitive("function") get used internally (as determined by grep-ing the source). So, if a user can't call it directly, who is the function meant for?

              – Artem Sokolov
              Feb 9 at 16:53








            • 2





              The function .Primitive("function") is called when you evaluate a call to function created by the parser into a function object created by the interpreter. Note that those two kinds of objects print identically, which can be confusing. Check the differences between quote(function(foo, bar) NULL) and the unquoted version. You can also verify with .Internal(inspect(quote(function(foo, bar) NULL))) that the parser correctly creates the formals list in calls to function.

              – lionel
              Feb 10 at 10:24














            • 1





              You’re spot on as far as your reasoning goes. I think the missing piece to the puzzle is the declaration of function in names.c: Unlike your own C function, do_function doesn’t get called with the evaluated argument; instead, it gets called with unevaluated arguments, so what gets passed isn’t a pairlist, it’s a quoted expression that would evaluate to a pairlist.

              – Konrad Rudolph
              Feb 9 at 10:07











            • @KonradRudolph: Do you think this is intended behavior? Neither do_function, nor `function`, nor .Primitive("function") get used internally (as determined by grep-ing the source). So, if a user can't call it directly, who is the function meant for?

              – Artem Sokolov
              Feb 9 at 16:53








            • 2





              The function .Primitive("function") is called when you evaluate a call to function created by the parser into a function object created by the interpreter. Note that those two kinds of objects print identically, which can be confusing. Check the differences between quote(function(foo, bar) NULL) and the unquoted version. You can also verify with .Internal(inspect(quote(function(foo, bar) NULL))) that the parser correctly creates the formals list in calls to function.

              – lionel
              Feb 10 at 10:24








            1




            1





            You’re spot on as far as your reasoning goes. I think the missing piece to the puzzle is the declaration of function in names.c: Unlike your own C function, do_function doesn’t get called with the evaluated argument; instead, it gets called with unevaluated arguments, so what gets passed isn’t a pairlist, it’s a quoted expression that would evaluate to a pairlist.

            – Konrad Rudolph
            Feb 9 at 10:07





            You’re spot on as far as your reasoning goes. I think the missing piece to the puzzle is the declaration of function in names.c: Unlike your own C function, do_function doesn’t get called with the evaluated argument; instead, it gets called with unevaluated arguments, so what gets passed isn’t a pairlist, it’s a quoted expression that would evaluate to a pairlist.

            – Konrad Rudolph
            Feb 9 at 10:07













            @KonradRudolph: Do you think this is intended behavior? Neither do_function, nor `function`, nor .Primitive("function") get used internally (as determined by grep-ing the source). So, if a user can't call it directly, who is the function meant for?

            – Artem Sokolov
            Feb 9 at 16:53







            @KonradRudolph: Do you think this is intended behavior? Neither do_function, nor `function`, nor .Primitive("function") get used internally (as determined by grep-ing the source). So, if a user can't call it directly, who is the function meant for?

            – Artem Sokolov
            Feb 9 at 16:53






            2




            2





            The function .Primitive("function") is called when you evaluate a call to function created by the parser into a function object created by the interpreter. Note that those two kinds of objects print identically, which can be confusing. Check the differences between quote(function(foo, bar) NULL) and the unquoted version. You can also verify with .Internal(inspect(quote(function(foo, bar) NULL))) that the parser correctly creates the formals list in calls to function.

            – lionel
            Feb 10 at 10:24





            The function .Primitive("function") is called when you evaluate a call to function created by the parser into a function object created by the interpreter. Note that those two kinds of objects print identically, which can be confusing. Check the differences between quote(function(foo, bar) NULL) and the unquoted version. You can also verify with .Internal(inspect(quote(function(foo, bar) NULL))) that the parser correctly creates the formals list in calls to function.

            – lionel
            Feb 10 at 10:24


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54596743%2fhow-do-i-call-the-function-function%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Index of /

            Tribalistas

            Listed building