Skip to content

use 'lgrow' helper for growing langsxps #1388

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
2025-06-02 Kevin Ushey <[email protected]>

* inst/include/Rcpp.h: Avoid copy when creating Language objects
* inst/include/Rcpp/Language.h: Idem
* inst/include/Rcpp/lgrow.h: Idem
* inst/tinytest/cpp/language.cpp: Idem
* inst/tinytest/test_language.R: Idem

2025-05-27 Dirk Eddelbuettel <[email protected]>

* DESCRIPTION (Version, Date): Roll micro version and date
Expand Down
2 changes: 2 additions & 0 deletions inst/NEWS.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
\itemize{
\item Changes in Rcpp API:
\itemize{
\item Fixed an issue where Rcpp::Language would duplicate its arguments
(Kevin in \ghpr{1388}, fixing \ghit{1386})
\item The \code{std::string_view} type is now covered by \code{wrap()}
(Lev Kandel in \ghpr{1356} as discussed in \ghit{1357})
\item A last remaining \code{DATAPTR} use has been converted to
Expand Down
1 change: 1 addition & 0 deletions inst/include/Rcpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <Rcpp/Reference.h>
#include <Rcpp/clone.h>
#include <Rcpp/grow.h>
#include <Rcpp/lgrow.h>
#include <Rcpp/Dimension.h>

#include <Rcpp/Symbol.h>
Expand Down
4 changes: 2 additions & 2 deletions inst/include/Rcpp/Language.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,12 @@ namespace Rcpp{
*/
template <typename... T>
Language_Impl(const std::string& symbol, const T&... t) {
Storage::set__(pairlist(Rf_install(symbol.c_str()), t...) );
Storage::set__(langlist(Rf_install(symbol.c_str()), t...) );
}

template <typename... T>
Language_Impl(const Function& function, const T&... t) {
Storage::set__(pairlist(function, t...));
Storage::set__(langlist(function, t...));
}

/**
Expand Down
77 changes: 77 additions & 0 deletions inst/include/Rcpp/lgrow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
//
// lgrow.h: Rcpp R/C++ interface class library -- grow a (LANGSXP) pairlist
//
// Copyright (C) 2010 - 2025 Dirk Eddelbuettel, Romain Francois, and Kevin Ushey
//
// This file is part of Rcpp.
//
// Rcpp is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// Rcpp is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.

#ifndef Rcpp_lgrow_h
#define Rcpp_lgrow_h

#include <RcppCommon.h>
#include <Rcpp/Named.h>

namespace Rcpp {

inline SEXP lgrow(SEXP head, SEXP tail) {
return Rf_lcons(head, tail);
}

namespace internal {

// for Named objects
template <typename T>
inline SEXP lgrow__dispatch(Rcpp::traits::true_type, const T& head, SEXP tail) {
Shield<SEXP> y(wrap(head.object));
Shield<SEXP> x(Rf_lcons(y, tail));
SEXP headNameSym = Rf_install(head.name.c_str());
SET_TAG(x, headNameSym);
return x;
}

// for all other objects
template <typename T>
inline SEXP lgrow__dispatch(Rcpp::traits::false_type, const T& head, SEXP tail) {
return lgrow(wrap(head), tail);
}

} // internal

template <typename T>
SEXP lgrow(const T& head, SEXP tail) {
Shield<SEXP> y(tail);
return internal::lgrow__dispatch(typename traits::is_named<T>::type(), head, y);
}

inline SEXP lgrow(const char* head, SEXP tail) {
Shield<SEXP> y(tail);
return lgrow(Rf_mkString(head), y);
}

template <typename T1>
SEXP langlist(const T1& t1) {
return lgrow(t1, R_NilValue);
}

template <typename T, typename... TArgs>
SEXP langlist(const T& t1, const TArgs&... args) {
return lgrow(t1, langlist(args...));
}

} // namespace Rcpp

#endif
7 changes: 7 additions & 0 deletions inst/tinytest/cpp/language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,10 @@ Formula runit_formula_SEXP(SEXP form){
return f;
}

// [[Rcpp::export]]
SEXP runit_language_modify(Function f) {
auto v = NumericVector::create(0.0, 1.0);
Rcpp::Language call(f, v);
v[0] = 999.0;
return CADR(call);
}
2 changes: 2 additions & 0 deletions inst/tinytest/test_language.R
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,5 @@ expect_equal( runit_formula_SEXP( "x ~ y + z" ), x ~ y + z, info = "Formula( SEX
expect_equal( runit_formula_SEXP( parse( text = "x ~ y + z") ), x ~ y + z, info = "Formula( SEXP = EXPRSXP )" )
expect_equal( runit_formula_SEXP( list( "x ~ y + z") ), x ~ y + z, info = "Formula( SEXP = VECSXP(1 = STRSXP) )" )
expect_equal( runit_formula_SEXP( list( x ~ y + z) ), x ~ y + z, info = "Formula( SEXP = VECSXP(1 = formula) )" )

expect_equal( runit_language_modify(sum), c(999, 1), info = "Language objects don't duplicate their arguments" )