Skip to content

Commit c564e36

Browse files
committed
use 'lgrow' helper for growing langsxps
1 parent d8c084a commit c564e36

File tree

6 files changed

+97
-2
lines changed

6 files changed

+97
-2
lines changed

ChangeLog

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
2025-06-02 Kevin Ushey <[email protected]>
2+
3+
* inst/include/Rcpp.h: Avoid copy when creating Language objects
4+
* inst/include/Rcpp/Language.h: Idem
5+
* inst/tinytest/cpp/language.cpp: Idem
6+
* inst/tinytest/test_language.R: Idem
7+
* inst/include/Rcpp/lgrow.h: Idem
8+
19
2025-05-27 Dirk Eddelbuettel <[email protected]>
210

311
* DESCRIPTION (Version, Date): Roll micro version and date

inst/include/Rcpp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <Rcpp/Reference.h>
3333
#include <Rcpp/clone.h>
3434
#include <Rcpp/grow.h>
35+
#include <Rcpp/lgrow.h>
3536
#include <Rcpp/Dimension.h>
3637

3738
#include <Rcpp/Symbol.h>

inst/include/Rcpp/Language.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,12 @@ namespace Rcpp{
104104
*/
105105
template <typename... T>
106106
Language_Impl(const std::string& symbol, const T&... t) {
107-
Storage::set__(pairlist(Rf_install(symbol.c_str()), t...) );
107+
Storage::set__(langlist(Rf_install(symbol.c_str()), t...) );
108108
}
109109

110110
template <typename... T>
111111
Language_Impl(const Function& function, const T&... t) {
112-
Storage::set__(pairlist(function, t...));
112+
Storage::set__(langlist(function, t...));
113113
}
114114

115115
/**

inst/include/Rcpp/lgrow.h

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
2+
//
3+
// lgrow.h: Rcpp R/C++ interface class library -- grow a (LANGSXP) pairlist
4+
//
5+
// Copyright (C) 2010 - 2025 Dirk Eddelbuettel and Romain Francois
6+
//
7+
// This file is part of Rcpp.
8+
//
9+
// Rcpp is free software: you can redistribute it and/or modify it
10+
// under the terms of the GNU General Public License as published by
11+
// the Free Software Foundation, either version 2 of the License, or
12+
// (at your option) any later version.
13+
//
14+
// Rcpp is distributed in the hope that it will be useful, but
15+
// WITHOUT ANY WARRANTY; without even the implied warranty of
16+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
// GNU General Public License for more details.
18+
//
19+
// You should have received a copy of the GNU General Public License
20+
// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
21+
22+
#ifndef Rcpp_lgrow_h
23+
#define Rcpp_lgrow_h
24+
25+
#include <RcppCommon.h>
26+
#include <Rcpp/Named.h>
27+
28+
namespace Rcpp {
29+
30+
inline SEXP lgrow(SEXP head, SEXP tail) {
31+
return LCONS(head, tail);
32+
}
33+
34+
namespace internal {
35+
36+
// for Named objects
37+
template <typename T>
38+
inline SEXP lgrow__dispatch(Rcpp::traits::true_type, const T& head, SEXP tail) {
39+
Shield<SEXP> y(wrap(head.object));
40+
Shield<SEXP> x(Rf_lcons(y, tail));
41+
SEXP headNameSym = Rf_install(head.name.c_str());
42+
SET_TAG(x, headNameSym);
43+
return x;
44+
}
45+
46+
// for all other objects
47+
template <typename T>
48+
inline SEXP lgrow__dispatch(Rcpp::traits::false_type, const T& head, SEXP tail) {
49+
return lgrow(wrap(head), tail);
50+
}
51+
52+
} // internal
53+
54+
template <typename T>
55+
SEXP lgrow(const T& head, SEXP tail) {
56+
Shield<SEXP> y(tail);
57+
return internal::lgrow__dispatch(typename traits::is_named<T>::type(), head, y);
58+
}
59+
60+
inline SEXP lgrow(const char* head, SEXP tail) {
61+
Shield<SEXP> y(tail);
62+
return lgrow(Rf_mkString(head), y);
63+
}
64+
65+
template <typename T1>
66+
SEXP langlist(const T1& t1) {
67+
return lgrow(t1, R_NilValue);
68+
}
69+
70+
template <typename T, typename... TArgs>
71+
SEXP langlist(const T& t1, const TArgs&... args) {
72+
return lgrow(t1, langlist(args...));
73+
}
74+
75+
} // namespace Rcpp
76+
77+
#endif

inst/tinytest/cpp/language.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,10 @@ Formula runit_formula_SEXP(SEXP form){
272272
return f;
273273
}
274274

275+
// [[Rcpp::export]]
276+
SEXP runit_language_modify(Function f) {
277+
auto v = NumericVector::create(0.0, 1.0);
278+
Rcpp::Language call(f, v);
279+
v[0] = 999.0;
280+
return CADR(call);
281+
}

inst/tinytest/test_language.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,5 @@ expect_equal( runit_formula_SEXP( "x ~ y + z" ), x ~ y + z, info = "Formula( SEX
139139
expect_equal( runit_formula_SEXP( parse( text = "x ~ y + z") ), x ~ y + z, info = "Formula( SEXP = EXPRSXP )" )
140140
expect_equal( runit_formula_SEXP( list( "x ~ y + z") ), x ~ y + z, info = "Formula( SEXP = VECSXP(1 = STRSXP) )" )
141141
expect_equal( runit_formula_SEXP( list( x ~ y + z) ), x ~ y + z, info = "Formula( SEXP = VECSXP(1 = formula) )" )
142+
143+
expect_equal( runit_language_modify(sum), c(999, 1), info = "Language objects don't duplicate their arguments" )

0 commit comments

Comments
 (0)