Discussion:
[Rcpp-devel] coercion NULL to vector
Serguei Sokol
2018-04-17 13:09:30 UTC
Permalink
Hi,

I would like to re-discuss the subject of automatic coercion of
NULL to some vector in function parameter list. This old topic was
already raised e.g. here
https://stackoverflow.com/questions/34718570/rcpp-pass-vector-of-length-0-null-to-cppfunction

To resume, actually a function defined as (ivec is from RcppArmadillo package)

sourceCpp(code="
    // [[Rcpp::depends(RcppArmadillo)]]
    #include <RcppArmadillo.h>
    using namespace arma;
    // [[Rcpp::export]]
    ivec f(ivec x) {return x+1;}
")

and called as f(c()) will produce an error:
Error in f(c()) :
  Not compatible with requested type: [type=NULL; target=integer].
f(integer(0))
     [,1]

The following one-line patch would do the job:
diff --git a/inst/include/Rcpp/r_cast.h b/inst/include/Rcpp/r_cast.h
index e59fa799..c0ec0817 100644
--- a/inst/include/Rcpp/r_cast.h
+++ b/inst/include/Rcpp/r_cast.h
@@ -63,6 +63,7 @@ namespace Rcpp {
             case LGLSXP:
             case CPLXSXP:
             case INTSXP:
+            case NILSXP:
                 return Rf_coerceVector(x, RTYPE);
             default:
                 const char* fmt = "Not compatible with requested type: "

It will automatically coerce NULL to a declared vector type.
It's a more primitive solution than Nullable<T> but in many cases
it can be largely sufficient and make code look shorter and clearer.

Will it break something in established usage habits? Is it compatible with your plans for Rcpp?
I can prepare a PR if you decide to include it.

Best,
Serguei.
Dirk Eddelbuettel
2018-04-17 15:31:26 UTC
Permalink
On 17 April 2018 at 15:09, Serguei Sokol wrote:
| Hi,
|
| I would like to re-discuss the subject of automatic coercion of
| NULL to some vector in function parameter list. This old topic was
| already raised e.g. here
| https://stackoverflow.com/questions/34718570/rcpp-pass-vector-of-length-0-null-to-cppfunction
|
| To resume, actually a function defined as (ivec is from RcppArmadillo package)
|
| sourceCpp(code="
|     // [[Rcpp::depends(RcppArmadillo)]]
|     #include <RcppArmadillo.h>
|     using namespace arma;
|     // [[Rcpp::export]]
|     ivec f(ivec x) {return x+1;}
| ")
|
| and called as f(c()) will produce an error:
| Error in f(c()) :
|   Not compatible with requested type: [type=NULL; target=integer].
|
| What I propose is (for this example) to mimic a call f(integer(0)) which gives:
| > f(integer(0))
|      [,1]
|
| The following one-line patch would do the job:
| diff --git a/inst/include/Rcpp/r_cast.h b/inst/include/Rcpp/r_cast.h
| index e59fa799..c0ec0817 100644
| --- a/inst/include/Rcpp/r_cast.h
| +++ b/inst/include/Rcpp/r_cast.h
| @@ -63,6 +63,7 @@ namespace Rcpp {
|              case LGLSXP:
|              case CPLXSXP:
|              case INTSXP:
| +            case NILSXP:
|                  return Rf_coerceVector(x, RTYPE);
|              default:
|                  const char* fmt = "Not compatible with requested type: "
|
| It will automatically coerce NULL to a declared vector type.
| It's a more primitive solution than Nullable<T> but in many cases
| it can be largely sufficient and make code look shorter and clearer.
|
| Will it break something in established usage habits? Is it compatible with your plans for Rcpp?
| I can prepare a PR if you decide to include it.

We could test that. It may not do harm -- so I just turned on a rev.dep
check for it.

Can you open an issue for it on GH though? Better visibility and easier 'per
concrete topic' discussion.

Dirk
--
http://dirk.eddelbuettel.com | @eddelbuettel | ***@debian.org
Dirk Eddelbuettel
2018-04-17 15:53:48 UTC
Permalink
On 17 April 2018 at 10:31, Dirk Eddelbuettel wrote:
|
| On 17 April 2018 at 15:09, Serguei Sokol wrote:
| | Hi,
| |
| | I would like to re-discuss the subject of automatic coercion of
| | NULL to some vector in function parameter list. This old topic was
| | already raised e.g. here
| | https://stackoverflow.com/questions/34718570/rcpp-pass-vector-of-length-0-null-to-cppfunction
| |
| | To resume, actually a function defined as (ivec is from RcppArmadillo package)
| |
| | sourceCpp(code="
| |     // [[Rcpp::depends(RcppArmadillo)]]
| |     #include <RcppArmadillo.h>
| |     using namespace arma;
| |     // [[Rcpp::export]]
| |     ivec f(ivec x) {return x+1;}
| | ")
| |
| | and called as f(c()) will produce an error:
| | Error in f(c()) :
| |   Not compatible with requested type: [type=NULL; target=integer].
| |
| | What I propose is (for this example) to mimic a call f(integer(0)) which gives:
| | > f(integer(0))
| |      [,1]
| |
| | The following one-line patch would do the job:
| | diff --git a/inst/include/Rcpp/r_cast.h b/inst/include/Rcpp/r_cast.h
| | index e59fa799..c0ec0817 100644
| | --- a/inst/include/Rcpp/r_cast.h
| | +++ b/inst/include/Rcpp/r_cast.h
| | @@ -63,6 +63,7 @@ namespace Rcpp {
| |              case LGLSXP:
| |              case CPLXSXP:
| |              case INTSXP:
| | +            case NILSXP:
| |                  return Rf_coerceVector(x, RTYPE);
| |              default:
| |                  const char* fmt = "Not compatible with requested type: "
| |
| | It will automatically coerce NULL to a declared vector type.
| | It's a more primitive solution than Nullable<T> but in many cases
| | it can be largely sufficient and make code look shorter and clearer.
| |
| | Will it break something in established usage habits? Is it compatible with your plans for Rcpp?
| | I can prepare a PR if you decide to include it.
|
| We could test that. It may not do harm -- so I just turned on a rev.dep
| check for it.
|
| Can you open an issue for it on GH though? Better visibility and easier 'per
| concrete topic' discussion.

I am not convinced that the semantics are useful. Your example works on the
sourceCpp("/tmp/serguei.cpp")
f(NULL)
[,1]
f(integer(0))
[,1]
f()
Error in f() : argument "x" is missing, with no default
class(f(NULL))
[1] "matrix"
But if I do the same with Rcpp types, say a matrix via

// [[Rcpp::export]]
Rcpp::NumericMatrix g(Rcpp::NumericMatrix x) { return x+1; }

then I get more restrictive behaviour (as NumericMatrix tests for matrix)
sourceCpp("/tmp/serguei.cpp")
g(NULL)
Error in g(NULL) : Not a matrix.
g(matrix())
[,1]
[1,] NA
g(vector())
Error in g(vector()) : Not a matrix.
g(integer())
Error in g(integer()) : Not a matrix.
Is this really useful, and can you not use Nullable<> instead?

Dirk
--
http://dirk.eddelbuettel.com | @eddelbuettel | ***@debian.org
Serguei Sokol
2018-04-18 09:56:41 UTC
Permalink
Post by Dirk Eddelbuettel
|
...
Post by Dirk Eddelbuettel
| | It will automatically coerce NULL to a declared vector type.
| | It's a more primitive solution than Nullable<T> but in many cases
| | it can be largely sufficient and make code look shorter and clearer.
| |
| | Will it break something in established usage habits? Is it compatible with your plans for Rcpp?
| | I can prepare a PR if you decide to include it.
|
| We could test that. It may not do harm -- so I just turned on a rev.dep
| check for it.
|
| Can you open an issue for it on GH though? Better visibility and easier 'per
| concrete topic' discussion.
I was just about to do so when I saw your post here. So let decide if
the semantic is useful or not and if yes, we'll switch to GH. OK?
Post by Dirk Eddelbuettel
I am not convinced that the semantics are useful. Your example works on the
What is returned: a matrix or a vector is not important here. By the way, it is
already resolved by an optional RCPP_ARMADILLO_RETURN_COLVEC_AS_VECTOR macro, remember?
The point here is how the /input/ NULL is interpreted. Is it coerced to smth or
just an error is thrown?
Post by Dirk Eddelbuettel
sourceCpp("/tmp/serguei.cpp")
f(NULL)
[,1]
f(integer(0))
[,1]
f()
Error in f() : argument "x" is missing, with no default
Normal. If you want to make the parameter optional, you have to declare
vec f(Rcpp::NumericVector x=R_NilValue) {return x+1;}
Post by Dirk Eddelbuettel
f()
[,1]
It does not work yet with 'vec' type but it could with an appropriate patch.
We are just discussing the usefulness of semantics not yet the patch.
Post by Dirk Eddelbuettel
class(f(NULL))
[1] "matrix"
(not a big deal what is returned as discussed above).
Post by Dirk Eddelbuettel
But if I do the same with Rcpp types, say a matrix via
// [[Rcpp::export]]
Rcpp::NumericMatrix g(Rcpp::NumericMatrix x) { return x+1; }
then I get more restrictive behaviour (as NumericMatrix tests for matrix)
Right. I think that the next logical step would be to allow an automatic
coercion of atomic vectors to matrices too. As in R
Post by Dirk Eddelbuettel
as.matrix(integer(0))
[,1]
we got a matrix of dims (0, 1) we could make the same available in Rcpp.
More generally, a vector x could be coerced into a matrix of dims (length(x), 1)
(once again just as in R as.matrix())
Post by Dirk Eddelbuettel
sourceCpp("/tmp/serguei.cpp")
g(NULL)
Error in g(NULL) : Not a matrix.
g(matrix())
[,1]
[1,] NA
g(vector())
Error in g(vector()) : Not a matrix.
g(integer())
Error in g(integer()) : Not a matrix.
Is this really useful, and can you not use Nullable<> instead?
Sure I can, but as I already said, my thought is to make the code
looking simpler and clearer in this kind of situations where automatic
coercion does sufficient job. Nullable<T> is much more flexible than that
but more expensive in coding on user's side.

Serguei.
Georgi Boshnakov
2018-04-18 10:26:34 UTC
Permalink
I may be missing something here but
it doesn't seem right to introduce silent coercion of NULL to vectors, etc.,
especially if it would become imposed on everybody using Rcpp/Armadillo.
Even the "convenience" of this is questionable.

Georgi Boshnakov


-----Original Message-----
From: rcpp-devel-***@lists.r-forge.r-project.org [mailto:rcpp-devel-***@lists.r-forge.r-project.org] On Behalf Of Serguei Sokol
Sent: 18 April 2018 10:57
To: Dirk Eddelbuettel
Cc: Rcpp-devel
Subject: Re: [Rcpp-devel] coercion NULL to vector
Post by Dirk Eddelbuettel
|
...
Post by Dirk Eddelbuettel
| | It will automatically coerce NULL to a declared vector type.
| | It's a more primitive solution than Nullable<T> but in many cases
| | it can be largely sufficient and make code look shorter and clearer.
| |
| | Will it break something in established usage habits? Is it compatible with your plans for Rcpp?
| | I can prepare a PR if you decide to include it.
|
| We could test that. It may not do harm -- so I just turned on a
| rev.dep check for it.
|
| Can you open an issue for it on GH though? Better visibility and
| easier 'per concrete topic' discussion.
I was just about to do so when I saw your post here. So let decide if the semantic is useful or not and if yes, we'll switch to GH. OK?
Post by Dirk Eddelbuettel
I am not convinced that the semantics are useful. Your example works
What is returned: a matrix or a vector is not important here. By the way, it is already resolved by an optional RCPP_ARMADILLO_RETURN_COLVEC_AS_VECTOR macro, remember?
The point here is how the /input/ NULL is interpreted. Is it coerced to smth or just an error is thrown?
Post by Dirk Eddelbuettel
sourceCpp("/tmp/serguei.cpp")
f(NULL)
[,1]
f(integer(0))
[,1]
f()
Error in f() : argument "x" is missing, with no default
Normal. If you want to make the parameter optional, you have to declare vec f(Rcpp::NumericVector x=R_NilValue) {return x+1;} > f()
[,1]
It does not work yet with 'vec' type but it could with an appropriate patch.
We are just discussing the usefulness of semantics not yet the patch.
Post by Dirk Eddelbuettel
class(f(NULL))
[1] "matrix"
(not a big deal what is returned as discussed above).
Post by Dirk Eddelbuettel
But if I do the same with Rcpp types, say a matrix via
// [[Rcpp::export]]
Rcpp::NumericMatrix g(Rcpp::NumericMatrix x) { return x+1; }
then I get more restrictive behaviour (as NumericMatrix tests for matrix)
Right. I think that the next logical step would be to allow an automatic coercion of atomic vectors to matrices too. As in R > as.matrix(integer(0))
[,1]
we got a matrix of dims (0, 1) we could make the same available in Rcpp.
More generally, a vector x could be coerced into a matrix of dims (length(x), 1) (once again just as in R as.matrix())
Post by Dirk Eddelbuettel
sourceCpp("/tmp/serguei.cpp")
g(NULL)
Error in g(NULL) : Not a matrix.
g(matrix())
[,1]
[1,] NA
g(vector())
Error in g(vector()) : Not a matrix.
g(integer())
Error in g(integer()) : Not a matrix.
Is this really useful, and can you not use Nullable<> instead?
Sure I can, but as I already said, my thought is to make the code looking simpler and clearer in this kind of situations where automatic coercion does sufficient job. Nullable<T> is much more flexible than that but more expensive in coding on user's side.

Serguei.
_______________________________________________
Rcpp-devel mailing list
Rcpp-***@lists.r-forge.r-project.org
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
Dirk Eddelbuettel
2018-04-18 11:32:16 UTC
Permalink
On 18 April 2018 at 10:26, Georgi Boshnakov wrote:
| I may be missing something here but
| it doesn't seem right to introduce silent coercion of NULL to vectors, etc.,
| especially if it would become imposed on everybody using Rcpp/Armadillo.
| Even the "convenience" of this is questionable.

Agreed. I am also not yet convinced by Serguei's argument. It seems a little
invasive for an unclear (to me) use case.

Dirk
--
http://dirk.eddelbuettel.com | @eddelbuettel | ***@debian.org
Serguei Sokol
2018-04-18 13:09:23 UTC
Permalink
Post by Dirk Eddelbuettel
| I may be missing something here but
| it doesn't seem right to introduce silent coercion of NULL to vectors, etc.,
| especially if it would become imposed on everybody using Rcpp/Armadillo.
| Even the "convenience" of this is questionable.
Agreed. I am also not yet convinced by Serguei's argument. It seems a little
invasive for an unclear (to me) use case.
I can describe my own case which made me search for a such solution.
I have an Rcpp/Armadillo function accepting in an optional argument a vector of uvec type.
It can be called from R and I can call it from other C++ functions of the same package too.
Nullable<IntegerVector> mechanism was cumbersome but sufficient (note that there is no possible Nullable<uvec>)
when only R calls were planned. But when it comes to calls from C++ I'll have to juggle with wrap() too.
Both of Nullable<T> (as well as special code for dealing with NULL case) and wrap()
become unnecessary with a neat declaration f(..., uvec v, ...). So that
an R call with 'c()' can pass as well as C++ calls with an empty uvec without
any additional hassle for treating NULL case.

Serguei.
Serguei Sokol
2018-04-18 12:51:02 UTC
Permalink
Post by Georgi Boshnakov
I may be missing something here but
it doesn't seem right to introduce silent coercion of NULL to vectors, etc.,
especially if it would become imposed on everybody using Rcpp/Armadillo.
Nothing is imposed. Everyone will be free to use Nullable<T> mechanism as before.
Actually, when NULL is provided to where a vector or a matrix is expected
just an error is thrown. So we can hardly imagine that someone would have
his program broken or will be misled if such coercion is introduced.
Post by Georgi Boshnakov
Even the "convenience" of this is questionable.
Right. It's a matter of taste. But with a quick glance on SO
I have seen a discussion here
https://stackoverflow.com/questions/34718570/rcpp-pass-vector-of-length-0-null-to-cppfunction
and on this list here (and follow-ups)
http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2014-February/007215.html
where some people are surprised not having such coercion and even
expressed a wish like "I would be super happy if in the future the special value
R_NilValue could be converted to an empty vector, it would make things
very easy and coherent with R's behaviour."
It's also my thought but I am ready to hear the arguments of those who
think otherwise.

Serguei.
Post by Georgi Boshnakov
Georgi Boshnakov
-----Original Message-----
Sent: 18 April 2018 10:57
To: Dirk Eddelbuettel
Cc: Rcpp-devel
Subject: Re: [Rcpp-devel] coercion NULL to vector
Post by Dirk Eddelbuettel
|
...
Post by Dirk Eddelbuettel
| | It will automatically coerce NULL to a declared vector type.
| | It's a more primitive solution than Nullable<T> but in many cases
| | it can be largely sufficient and make code look shorter and clearer.
| |
| | Will it break something in established usage habits? Is it compatible with your plans for Rcpp?
| | I can prepare a PR if you decide to include it.
|
| We could test that. It may not do harm -- so I just turned on a
| rev.dep check for it.
|
| Can you open an issue for it on GH though? Better visibility and
| easier 'per concrete topic' discussion.
I was just about to do so when I saw your post here. So let decide if the semantic is useful or not and if yes, we'll switch to GH. OK?
Post by Dirk Eddelbuettel
I am not convinced that the semantics are useful. Your example works
What is returned: a matrix or a vector is not important here. By the way, it is already resolved by an optional RCPP_ARMADILLO_RETURN_COLVEC_AS_VECTOR macro, remember?
The point here is how the /input/ NULL is interpreted. Is it coerced to smth or just an error is thrown?
Post by Dirk Eddelbuettel
sourceCpp("/tmp/serguei.cpp")
f(NULL)
[,1]
f(integer(0))
[,1]
f()
Error in f() : argument "x" is missing, with no default
Normal. If you want to make the parameter optional, you have to declare vec f(Rcpp::NumericVector x=R_NilValue) {return x+1;} > f()
[,1]
It does not work yet with 'vec' type but it could with an appropriate patch.
We are just discussing the usefulness of semantics not yet the patch.
Post by Dirk Eddelbuettel
class(f(NULL))
[1] "matrix"
(not a big deal what is returned as discussed above).
Post by Dirk Eddelbuettel
But if I do the same with Rcpp types, say a matrix via
// [[Rcpp::export]]
Rcpp::NumericMatrix g(Rcpp::NumericMatrix x) { return x+1; }
then I get more restrictive behaviour (as NumericMatrix tests for matrix)
Right. I think that the next logical step would be to allow an automatic coercion of atomic vectors to matrices too. As in R > as.matrix(integer(0))
[,1]
we got a matrix of dims (0, 1) we could make the same available in Rcpp.
More generally, a vector x could be coerced into a matrix of dims (length(x), 1) (once again just as in R as.matrix())
Post by Dirk Eddelbuettel
sourceCpp("/tmp/serguei.cpp")
g(NULL)
Error in g(NULL) : Not a matrix.
g(matrix())
[,1]
[1,] NA
g(vector())
Error in g(vector()) : Not a matrix.
g(integer())
Error in g(integer()) : Not a matrix.
Is this really useful, and can you not use Nullable<> instead?
Sure I can, but as I already said, my thought is to make the code looking simpler and clearer in this kind of situations where automatic coercion does sufficient job. Nullable<T> is much more flexible than that but more expensive in coding on user's side.
Serguei.
_______________________________________________
Rcpp-devel mailing list
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
Dirk Eddelbuettel
2018-04-18 13:59:19 UTC
Permalink
Serguei,

(Extra line breaks help readibility on text only mail readers)

On 18 April 2018 at 14:51, Serguei Sokol wrote:
| Le 18/04/2018 à 12:26, Georgi Boshnakov a écrit :
| > I may be missing something here but
| > it doesn't seem right to introduce silent coercion of NULL to vectors, etc.,
| > especially if it would become imposed on everybody using Rcpp/Armadillo.
| Nothing is imposed. Everyone will be free to use Nullable<T> mechanism as before.
| Actually, when NULL is provided to where a vector or a matrix is expected
| just an error is thrown. So we can hardly imagine that someone would have
| his program broken or will be misled if such coercion is introduced.
|
| > Even the "convenience" of this is questionable.
| Right. It's a matter of taste. But with a quick glance on SO
| I have seen a discussion here
| https://stackoverflow.com/questions/34718570/rcpp-pass-vector-of-length-0-null-to-cppfunction
| and on this list here (and follow-ups)
| http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2014-February/007215.html
| where some people are surprised not having such coercion and even
| expressed a wish like "I would be super happy if in the future the special value
| R_NilValue could be converted to an empty vector, it would make things
| very easy and coherent with R's behaviour."
| It's also my thought but I am ready to hear the arguments of those who
| think otherwise.

I am not religious about it. Adding the one line is something we might be
able to do. I did a partial rev.dep tests and it showed no issues. But I
would like other Rcpp Core folks to weigh in too.

On 18 April 2018 at 15:09, Serguei Sokol wrote:
| Le 18/04/2018 à 13:32, Dirk Eddelbuettel a écrit :
| >
| > On 18 April 2018 at 10:26, Georgi Boshnakov wrote:
| > | I may be missing something here but
| > | it doesn't seem right to introduce silent coercion of NULL to vectors, etc.,
| > | especially if it would become imposed on everybody using Rcpp/Armadillo.
| > | Even the "convenience" of this is questionable.
| >
| > Agreed. I am also not yet convinced by Serguei's argument. It seems a little
| > invasive for an unclear (to me) use case.
| I can describe my own case which made me search for a such solution.
| I have an Rcpp/Armadillo function accepting in an optional argument a vector of uvec type.
| It can be called from R and I can call it from other C++ functions of the same package too.
| Nullable<IntegerVector> mechanism was cumbersome but sufficient (note that there is no possible Nullable<uvec>)

It needs to be as<>()/wrap() convertible to/from SEXP, yes.

| when only R calls were planned. But when it comes to calls from C++ I'll have to juggle with wrap() too.
| Both of Nullable<T> (as well as special code for dealing with NULL case) and wrap()
| become unnecessary with a neat declaration f(..., uvec v, ...). So that
| an R call with 'c()' can pass as well as C++ calls with an empty uvec without
| any additional hassle for treating NULL case.

Could you use XPtr ?

Dirk
--
http://dirk.eddelbuettel.com | @eddelbuettel | ***@debian.org
Jeff Newmiller
2018-04-18 14:15:44 UTC
Permalink
Regarding:

"Actually, when NULL is provided to where a vector or a matrix is expected just an error is thrown. So we can hardly imagine that someone would have his program broken or will be misled if such coercion is introduced."

If all programs were perfect this would be true, but the ability to identify incorrect pointer initialization is an important feature for testing.

In the late '90s, some Internet Service Providers tried to "assist" users who typed bad site names into browsers by making failed DNS lookups redirect to a server prepared to supply an informative "were you looking for X?" web page. This caused significant disruption in non-user-interactive network protocols that relied on getting a failure notice for bad DNS lookups, and that idea had to go to the trash heap eventually.

I don't have failed code tests to offer for this, but the idea of silently replacing a C++ NULL with a valid value is anathema.
Post by Dirk Eddelbuettel
Serguei,
(Extra line breaks help readibility on text only mail readers)
| > I may be missing something here but
| > it doesn't seem right to introduce silent coercion of NULL to vectors, etc.,
| > especially if it would become imposed on everybody using
Rcpp/Armadillo.
| Nothing is imposed. Everyone will be free to use Nullable<T>
mechanism as before.
| Actually, when NULL is provided to where a vector or a matrix is expected
| just an error is thrown. So we can hardly imagine that someone would have
| his program broken or will be misled if such coercion is introduced.
|
| > Even the "convenience" of this is questionable.
| Right. It's a matter of taste. But with a quick glance on SO
| I have seen a discussion here
|
https://stackoverflow.com/questions/34718570/rcpp-pass-vector-of-length-0-null-to-cppfunction
| and on this list here (and follow-ups)
|
http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2014-February/007215.html
| where some people are surprised not having such coercion and even
| expressed a wish like "I would be super happy if in the future the special value
| R_NilValue could be converted to an empty vector, it would make things
| very easy and coherent with R's behaviour."
| It's also my thought but I am ready to hear the arguments of those who
| think otherwise.
I am not religious about it. Adding the one line is something we might be
able to do. I did a partial rev.dep tests and it showed no issues. But I
would like other Rcpp Core folks to weigh in too.
| >
| > | I may be missing something here but
| > | it doesn't seem right to introduce silent coercion of NULL to vectors, etc.,
| > | especially if it would become imposed on everybody using
Rcpp/Armadillo.
| > | Even the "convenience" of this is questionable.
| >
| > Agreed. I am also not yet convinced by Serguei's argument. It seems a little
| > invasive for an unclear (to me) use case.
| I can describe my own case which made me search for a such solution.
| I have an Rcpp/Armadillo function accepting in an optional argument a vector of uvec type.
| It can be called from R and I can call it from other C++ functions of the same package too.
| Nullable<IntegerVector> mechanism was cumbersome but sufficient (note
that there is no possible Nullable<uvec>)
It needs to be as<>()/wrap() convertible to/from SEXP, yes.
| when only R calls were planned. But when it comes to calls from C++
I'll have to juggle with wrap() too.
| Both of Nullable<T> (as well as special code for dealing with NULL case) and wrap()
| become unnecessary with a neat declaration f(..., uvec v, ...). So that
| an R call with 'c()' can pass as well as C++ calls with an empty uvec without
| any additional hassle for treating NULL case.
Could you use XPtr ?
Dirk
--
Sent from my phone. Please excuse my brevity.
Serguei Sokol
2018-04-18 14:53:12 UTC
Permalink
Post by Jeff Newmiller
"Actually, when NULL is provided to where a vector or a matrix is expected just an error is thrown. So we can hardly imagine that someone would have his program broken or will be misled if such coercion is introduced."
If all programs were perfect this would be true, but the ability to identify incorrect pointer initialization is an important feature for testing.
In the late '90s, some Internet Service Providers tried to "assist" users who typed bad site names into browsers by making failed DNS lookups redirect to a server prepared to supply an informative "were you looking for X?" web page. This caused significant disruption in non-user-interactive network protocols that relied on getting a failure notice for bad DNS lookups, and that idea had to go to the trash heap eventually.
Interesting example but not really "parallel" to our situation.
In R, we already have as.numeric(NULL) without such kind of catastrophe.
I just propose an equivalent functioning in Rcpp.
Post by Jeff Newmiller
I don't have failed code tests to offer for this, but the idea of silently replacing a C++ NULL with a valid value is anathema.
It's not C++ NULL which is coerced (not "replaced") to a vector but R's one. And only where a vector of a given type is expected, not everywhere.

I think there is a possible compromise.
We can introduce an automatic coercion in #ifdef'ed blocks with e.g. RCPP_COERCE_NULL_TO_VECTOR and RCPP_COERCE_VECTOR_TO_MARIX optional macros.
In such a way, those who want this feature can have it by defining these macros before including Rcpp.h and those who consider it as anathema can go a
traditional way of doing.

Serguei.
Jeff Newmiller
2018-04-18 15:31:58 UTC
Permalink
as.numeric( NULL ) is not silent, it is very explicit.

Re this not being a C++ NULL, I don't object to R NULL being used that way (in fact it may be more sensible to do this than not, but it is not clear that R core thinks this way).
Post by Jeff Newmiller
Post by Jeff Newmiller
"Actually, when NULL is provided to where a vector or a matrix is
expected just an error is thrown. So we can hardly imagine that someone
would have his program broken or will be misled if such coercion is
introduced."
Post by Jeff Newmiller
If all programs were perfect this would be true, but the ability to
identify incorrect pointer initialization is an important feature for
testing.
Post by Jeff Newmiller
In the late '90s, some Internet Service Providers tried to "assist"
users who typed bad site names into browsers by making failed DNS
lookups redirect to a server prepared to supply an informative "were
you looking for X?" web page. This caused significant disruption in
non-user-interactive network protocols that relied on getting a failure
notice for bad DNS lookups, and that idea had to go to the trash heap
eventually.
Interesting example but not really "parallel" to our situation.
In R, we already have as.numeric(NULL) without such kind of
catastrophe.
I just propose an equivalent functioning in Rcpp.
Post by Jeff Newmiller
I don't have failed code tests to offer for this, but the idea of
silently replacing a C++ NULL with a valid value is anathema.
It's not C++ NULL which is coerced (not "replaced") to a vector but R's
one. And only where a vector of a given type is expected, not
everywhere.
I think there is a possible compromise.
We can introduce an automatic coercion in #ifdef'ed blocks with e.g.
RCPP_COERCE_NULL_TO_VECTOR and RCPP_COERCE_VECTOR_TO_MARIX optional
macros.
In such a way, those who want this feature can have it by defining
these macros before including Rcpp.h and those who consider it as
anathema can go a
traditional way of doing.
Serguei.
--
Sent from my phone. Please excuse my brevity.
Serguei Sokol
2018-04-18 15:53:02 UTC
Permalink
Post by Jeff Newmiller
as.numeric( NULL ) is not silent, it is very explicit.
Well, written in this way yes. But I was referring more to the content
than to the form. If you write as.numeric(x) and at some run-time point
x become NULL, the code won't stop with an error. It will silently
coerce NULL to numeric(0). Analogously in what I propose, if you write
f(vec x) and at some call x is NULL, f would continue to work as if
called with f(numeric(0)).
Post by Jeff Newmiller
Re this not being a C++ NULL, I don't object to R NULL being used that way (in fact it may be more sensible to do this than not, but it is not clear that R core thinks this way).
No sure to get your point here but never mind.

Serguei.

Serguei Sokol
2018-04-18 14:35:17 UTC
Permalink
Post by Dirk Eddelbuettel
Could you use XPtr ?
Probably yes, as I could use Nullable<> too. But at what price?
For me, the code would become far less readable.

Serguei.
Loading...