How do I call the `function` function?
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
add a comment |
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
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 whatfunctiondoes.
– Artem Sokolov
Feb 8 at 18:08
@ArtemSokolov … sure but that does exactly what mymean3definition 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
add a comment |
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
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
r
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 whatfunctiondoes.
– Artem Sokolov
Feb 8 at 18:08
@ArtemSokolov … sure but that does exactly what mymean3definition 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
add a comment |
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 whatfunctiondoes.
– Artem Sokolov
Feb 8 at 18:08
@ArtemSokolov … sure but that does exactly what mymean3definition 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
add a comment |
3 Answers
3
active
oldest
votes
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.
1
I actually tried quoting the formals (as well as usingalist), 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 becausefortakes a symbol and two expressions, for which there is parser syntax. There is no explicit parser syntax for creating a pairlist literal, which is whatfunction()takes.
– lionel
Feb 8 at 17:59
Indeed. I just figured out that you can call it with a manually generatedpairlist— but once again only indirectly because, as you said, there’s nopairlistliteral syntax.
– Konrad Rudolph
Feb 8 at 18:01
add a comment |
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.)
add a comment |
After digging a little bit through the source code, here are a few observations:
The actual function creation is done by mkCLOSXP(). This is what gets called by
function() {}, byas.function.default()and by.Primitive("function")(a.k.a.`function`)as.function.default()gets routed to do_asfunction(), which also calls CheckFormals(). However, it directly constructs these formals a few lines above that.As you pointed out, the other place where
CheckFormals()gets called is insidedo_function(). However, I don't thinkdo_function()gets called by anything other than.Primitive("function"), so this is the only situation whereCheckFormals()is called on the user's input.CheckFormals()does actually correctly validate apairlistobject.
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.
1
You’re spot on as far as your reasoning goes. I think the missing piece to the puzzle is the declaration offunctioninnames.c: Unlike your own C function,do_functiondoesn’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? Neitherdo_function, nor`function`, nor.Primitive("function")get used internally (as determined bygrep-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 tofunctioncreated 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 betweenquote(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 tofunction.
– lionel
Feb 10 at 10:24
add a comment |
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
});
}
});
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
Required, but never shown
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
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.
1
I actually tried quoting the formals (as well as usingalist), 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 becausefortakes a symbol and two expressions, for which there is parser syntax. There is no explicit parser syntax for creating a pairlist literal, which is whatfunction()takes.
– lionel
Feb 8 at 17:59
Indeed. I just figured out that you can call it with a manually generatedpairlist— but once again only indirectly because, as you said, there’s nopairlistliteral syntax.
– Konrad Rudolph
Feb 8 at 18:01
add a comment |
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.
1
I actually tried quoting the formals (as well as usingalist), 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 becausefortakes a symbol and two expressions, for which there is parser syntax. There is no explicit parser syntax for creating a pairlist literal, which is whatfunction()takes.
– lionel
Feb 8 at 17:59
Indeed. I just figured out that you can call it with a manually generatedpairlist— but once again only indirectly because, as you said, there’s nopairlistliteral syntax.
– Konrad Rudolph
Feb 8 at 18:01
add a comment |
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.
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.
answered Feb 8 at 17:53
lionellionel
3,0871721
3,0871721
1
I actually tried quoting the formals (as well as usingalist), 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 becausefortakes a symbol and two expressions, for which there is parser syntax. There is no explicit parser syntax for creating a pairlist literal, which is whatfunction()takes.
– lionel
Feb 8 at 17:59
Indeed. I just figured out that you can call it with a manually generatedpairlist— but once again only indirectly because, as you said, there’s nopairlistliteral syntax.
– Konrad Rudolph
Feb 8 at 18:01
add a comment |
1
I actually tried quoting the formals (as well as usingalist), 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 becausefortakes a symbol and two expressions, for which there is parser syntax. There is no explicit parser syntax for creating a pairlist literal, which is whatfunction()takes.
– lionel
Feb 8 at 17:59
Indeed. I just figured out that you can call it with a manually generatedpairlist— but once again only indirectly because, as you said, there’s nopairlistliteral 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
add a comment |
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.)
add a comment |
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.)
add a comment |
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.)
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.)
answered Feb 8 at 18:12
Konrad RudolphKonrad Rudolph
400k1017881037
400k1017881037
add a comment |
add a comment |
After digging a little bit through the source code, here are a few observations:
The actual function creation is done by mkCLOSXP(). This is what gets called by
function() {}, byas.function.default()and by.Primitive("function")(a.k.a.`function`)as.function.default()gets routed to do_asfunction(), which also calls CheckFormals(). However, it directly constructs these formals a few lines above that.As you pointed out, the other place where
CheckFormals()gets called is insidedo_function(). However, I don't thinkdo_function()gets called by anything other than.Primitive("function"), so this is the only situation whereCheckFormals()is called on the user's input.CheckFormals()does actually correctly validate apairlistobject.
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.
1
You’re spot on as far as your reasoning goes. I think the missing piece to the puzzle is the declaration offunctioninnames.c: Unlike your own C function,do_functiondoesn’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? Neitherdo_function, nor`function`, nor.Primitive("function")get used internally (as determined bygrep-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 tofunctioncreated 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 betweenquote(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 tofunction.
– lionel
Feb 10 at 10:24
add a comment |
After digging a little bit through the source code, here are a few observations:
The actual function creation is done by mkCLOSXP(). This is what gets called by
function() {}, byas.function.default()and by.Primitive("function")(a.k.a.`function`)as.function.default()gets routed to do_asfunction(), which also calls CheckFormals(). However, it directly constructs these formals a few lines above that.As you pointed out, the other place where
CheckFormals()gets called is insidedo_function(). However, I don't thinkdo_function()gets called by anything other than.Primitive("function"), so this is the only situation whereCheckFormals()is called on the user's input.CheckFormals()does actually correctly validate apairlistobject.
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.
1
You’re spot on as far as your reasoning goes. I think the missing piece to the puzzle is the declaration offunctioninnames.c: Unlike your own C function,do_functiondoesn’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? Neitherdo_function, nor`function`, nor.Primitive("function")get used internally (as determined bygrep-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 tofunctioncreated 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 betweenquote(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 tofunction.
– lionel
Feb 10 at 10:24
add a comment |
After digging a little bit through the source code, here are a few observations:
The actual function creation is done by mkCLOSXP(). This is what gets called by
function() {}, byas.function.default()and by.Primitive("function")(a.k.a.`function`)as.function.default()gets routed to do_asfunction(), which also calls CheckFormals(). However, it directly constructs these formals a few lines above that.As you pointed out, the other place where
CheckFormals()gets called is insidedo_function(). However, I don't thinkdo_function()gets called by anything other than.Primitive("function"), so this is the only situation whereCheckFormals()is called on the user's input.CheckFormals()does actually correctly validate apairlistobject.
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.
After digging a little bit through the source code, here are a few observations:
The actual function creation is done by mkCLOSXP(). This is what gets called by
function() {}, byas.function.default()and by.Primitive("function")(a.k.a.`function`)as.function.default()gets routed to do_asfunction(), which also calls CheckFormals(). However, it directly constructs these formals a few lines above that.As you pointed out, the other place where
CheckFormals()gets called is insidedo_function(). However, I don't thinkdo_function()gets called by anything other than.Primitive("function"), so this is the only situation whereCheckFormals()is called on the user's input.CheckFormals()does actually correctly validate apairlistobject.
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.
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 offunctioninnames.c: Unlike your own C function,do_functiondoesn’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? Neitherdo_function, nor`function`, nor.Primitive("function")get used internally (as determined bygrep-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 tofunctioncreated 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 betweenquote(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 tofunction.
– lionel
Feb 10 at 10:24
add a comment |
1
You’re spot on as far as your reasoning goes. I think the missing piece to the puzzle is the declaration offunctioninnames.c: Unlike your own C function,do_functiondoesn’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? Neitherdo_function, nor`function`, nor.Primitive("function")get used internally (as determined bygrep-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 tofunctioncreated 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 betweenquote(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 tofunction.
– 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
add a comment |
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.
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
Required, but never shown
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
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
Required, but never shown
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
Required, but never shown
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
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
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
functiondoes.– Artem Sokolov
Feb 8 at 18:08
@ArtemSokolov … sure but that does exactly what my
mean3definition 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