Home > Net >  Dynamically updated list in Rcpp stores only last value
Dynamically updated list in Rcpp stores only last value

Time:07-14

I have a NumericMatrix whose values are updated every iteration of a loop. I want to store the matrix in a List every iteration. The code below gives a minimal reproducible example. However, when I compile and run this in R, every element of the list is identical to the final matrix, rather than storing each matrix. Why would this be the case, and how can I fix it? This seems like a very simple problem, but I haven't been able to find a solution.

Example code:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
List updatingList(int n) {
  // Create a NumericMatrix that will be updated every step
  NumericMatrix mat(n, 2);
  for (int i=0; i < n; i  ) { // set the initial state of the susceptible hosts
    mat(i,0) = 0; // initial Th1 
    mat(i,1) = 1; // initial Th2
  }
  // create a List that will store mat every step
  List list(n);
  
  for (int j=0; j < n; j  ) {
    // store the value of mat
    list(j) = mat;
    // update mat
    for (int i=0; i < n; i  ) { 
      mat(i,0)  = 1; 
      mat(i,1)  = 1; 
    }
  }
  return(list);  
}

/*** R
updatingList(3)
*/

Example output:

> updatingList(3)
[[1]]
     [,1] [,2]
[1,]    3    4
[2,]    3    4
[3,]    3    4

[[2]]
     [,1] [,2]
[1,]    3    4
[2,]    3    4
[3,]    3    4

[[3]]
     [,1] [,2]
[1,]    3    4
[2,]    3    4
[3,]    3    4

CodePudding user response:

Welcome to StackOverflow, and what a gnarly question :) After a few years with R you become familiar with the 'copy-on-write' idiom. What you have here is, really, just one instance of the matrix so what you back is consequently always the same. As it is the same matrix. And that is, come to think (a bit) about it, a feature.

What you want here is so 'seal' the matrix value away. So all we need to change is one line:

    // store a deep copy of mat
    list(j) = clone(mat);

By requesting deep copies at each loop run you actually get distinct instances as you desire.

Output

> Rcpp::sourceCpp("answer.cpp")

> updatingList(3)
[[1]]
     [,1] [,2]
[1,]    0    1
[2,]    0    1
[3,]    0    1

[[2]]
     [,1] [,2]
[1,]    1    2
[2,]    1    2
[3,]    1    2

[[3]]
     [,1] [,2]
[1,]    2    3
[2,]    2    3
[3,]    2    3

> 
  • Related