title: Unable to use a `Symbol` for a `Group` with paper.js
body: <p>I want to do an animation of a reaction-diffusion system with <code>paper.js</code>. </p>
  
  <p>Here is a code which generates just one image:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;html&gt;
    &lt;head&gt;
      &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.2/paper-full.min.js"&gt;&lt;/script&gt;
      &lt;style&gt;
        canvas {
          width: 400px;
          height: 400px;
          border: black 3px solid;
        }
      &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
      &lt;script&gt;
        function subm_index(M, x){
          if (x&lt;0)
            return x+M;
          if(x &gt;= M)
            return x-M;
          return x;
        }
        function update_concentrations(X, L, DA, DB, f, k){ 
          var sum_a, sum_b, x1, y1, t;
          var m = X.A.length;
          var n = X.A[0].length;
          var A = new Array(m);
          var B = new Array(m);
          for(var i = 0; i &lt; m; i++){
            A[i] = new Array(n);
            B[i] = new Array(n);
          }        
          for(var x = 0; x &lt; m; x++) {
            for(var y = 0; y &lt; n; y++){
              sum_a = 0.0;
              sum_b = 0.0;
              for(var i = -1; i &lt;= 1; i++){
                for(var j = -1; j &lt;= 1; j++){
                  x1 = subm_index(m, x - i);
                  y1 = subm_index(n, y - j);
                  sum_a = sum_a + L[i+1][j+1] * X.A[x1][y1];
                  sum_b = sum_b + L[i+1][j+1] * X.B[x1][y1];
                }
              }
              t = X.A[x][y]*X.B[x][y]*X.B[x][y];
              A[x][y] = X.A[x][y] + DA*sum_a - t + f*(1-X.A[x][y]);
              B[x][y] = X.B[x][y] + DB*sum_b + t - (k+f)*X.B[x][y];
            }
          }
          return {A: A, B: B};
        }
        function iterate_Gray_Scott(X, L, DA, DB, f, k, n){
          for(var i = 0; i &lt; n; i++){
            X = update_concentrations(X, L, DA, DB, f, k); 
          }
          return X;
        }
        var L = [[0.05, 0.2, 0.05], [0.2, -1, 0.2], [0.05, 0.2, 0.05]];
        var DA = 1;
        var DB = 0.5;
        var f = 0.0545;
        var k = 0.062;
      &lt;/script&gt;
  
      &lt;script type="text/paperscript" canvas="quad"&gt;
        var pixels = 200;
        var gridSize = 2;
        var rectSize = 2;
  
        var A = new Array(pixels);
        var B = new Array(pixels);
        for(var i = 0; i &lt; pixels; i++){
          A[i] = new Array(pixels);
          B[i] = new Array(pixels);
          for(var j = 0; j &lt; pixels; j++){
            A[i][j] = 1;
            B[i][j] = Math.random() &lt; 0.98 ? 0 : 1;
          }
        }
        var X = {A: A, B: B};
  
        X = iterate_Gray_Scott(X, L, DA, DB, f, k, 1000);
        
        for(var y = 0; y &lt; pixels; y++){
          for(var x = 0; x &lt; pixels; x++){
            var color = {
            hue: X.B[x][y] * 360,
            saturation: 1,
            brightness: 1
           };
            var path = new Path.Rectangle(new Point(x, y) * gridSize, new Size(rectSize, rectSize));
            path.fillColor = color;
          }
        }
        project.activeLayer.position = view.center;
      &lt;/script&gt;
      &lt;canvas id="quad" resize&gt;&lt;/canvas&gt;
    &lt;/body&gt;
  &lt;/html&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>Now, here is a code which generates the animation:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;html&gt;
    &lt;head&gt;
      &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.2/paper-full.min.js"&gt;&lt;/script&gt;
      &lt;style&gt;
        canvas {
          width: 400px;
          height: 400px;
          border: black 3px solid;
        }
      &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
      &lt;script&gt;
        function subm_index(M, x){
          if (x&lt;0)
            return x+M;
          if(x &gt;= M)
            return x-M;
          return x;
        }
        function update_concentrations(X, L, DA, DB, f, k){ 
          var sum_a, sum_b, x1, y1, t;
          var m = X.A.length;
          var n = X.A[0].length;
          var A = new Array(m);
          var B = new Array(m);
          for(var i = 0; i &lt; m; i++){
            A[i] = new Array(n);
            B[i] = new Array(n);
          }        
          for(var x = 0; x &lt; m; x++) {
            for(var y = 0; y &lt; n; y++){
              sum_a = 0.0;
              sum_b = 0.0;
              for(var i = -1; i &lt;= 1; i++){
                for(var j = -1; j &lt;= 1; j++){
                  x1 = subm_index(m, x - i);
                  y1 = subm_index(n, y - j);
                  sum_a = sum_a + L[i+1][j+1] * X.A[x1][y1];
                  sum_b = sum_b + L[i+1][j+1] * X.B[x1][y1];
                }
              }
              t = X.A[x][y]*X.B[x][y]*X.B[x][y];
              A[x][y] = X.A[x][y] + DA*sum_a - t + f*(1-X.A[x][y]);
              B[x][y] = X.B[x][y] + DB*sum_b + t - (k+f)*X.B[x][y];
            }
          }
          return {A: A, B: B};
        }
        function iterate_Gray_Scott(X, L, DA, DB, f, k, n){
          for(var i = 0; i &lt; n; i++){
            X = update_concentrations(X, L, DA, DB, f, k); 
          }
          return X;
        }
        var L = [[0.05, 0.2, 0.05], [0.2, -1, 0.2], [0.05, 0.2, 0.05]];
        var DA = 1;
        var DB = 0.5;
        var f = 0.0545;
        var k = 0.062;
      &lt;/script&gt;
  
      &lt;script type="text/paperscript" canvas="quad"&gt;
        var pixels = 200;
        var gridSize = 2;
        var rectSize = 2;
        var A = new Array(pixels);
        var B = new Array(pixels);
        var Paths = new Array(pixels);
        for(var i = 0; i &lt; pixels; i++){
          A[i] = new Array(pixels);
          B[i] = new Array(pixels);
          Paths[i] = new Array(pixels);
          for(var j = 0; j &lt; pixels; j++){
            A[i][j] = 1;
            B[i][j] = Math.random() &lt; 0.99 ? 0 : 1;
          }
        }
        var X = {A: A, B: B};
  
        for(var y = 0; y &lt; pixels; y++){
          for(var x = 0; x &lt; pixels; x++){
            var color = {
            hue: X.B[x][y] * 360,
            saturation: 1,
            brightness: 1
           };
            Paths[x][y] = new Path.Rectangle(new Point(x, y) * gridSize, new Size(rectSize, rectSize));
            Paths[x][y].fillColor = color;
          }
        }
  
        var nframes = 100;
  
        var XX = new Array(nframes);
        XX[0] = X;
        for(var frm = 1; frm &lt; nframes; frm++){
          XX[frm] = iterate_Gray_Scott(XX[frm-1], L, DA, DB, f, k, frm);
        }
  
        project.activeLayer.position = view.center;
  
        function onFrame(event){
          console.log(event.count);
          if(event.count &lt; nframes){
            for(var y = 0; y &lt; pixels; y++){
              for(var x = 0; x &lt; pixels; x++){
                var color = {
                  hue: XX[event.count].B[x][y] * 360,
                  saturation: 1,
                  brightness: 1
                };
                Paths[x][y].fillColor = color;
              }
            }
          }
        }
      &lt;/script&gt;
  
      &lt;canvas id="quad" resize&gt;&lt;/canvas&gt;
    &lt;/body&gt;
  &lt;/html&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>It works but the animation is not fluid enough. This is due to the double loop in <code>onFrame</code>, which consumes some time.</p>
  
  <p>So I firstly tried to create an array containing <code>nframes</code> <code>Group</code> elements, each group containing <code>pixels*pixels</code> <code>Rectangle</code> elements. But this generated an out-of-memory. </p>
  
  <p>So I tried to use a <code>Symbol</code> to save some memory. The code is below but it does not work, there is not a single image appearing.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;html&gt;
    &lt;head&gt;
      &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.2/paper-full.min.js"&gt;&lt;/script&gt;
      &lt;style&gt;
        canvas {
          width: 400px;
          height: 400px;
          border: black 3px solid;
        }
      &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
      &lt;script&gt;
        function subm_index(M, x){
          if (x&lt;0)
            return x+M;
          if(x &gt;= M)
            return x-M;
          return x;
        }
        function update_concentrations(X, L, DA, DB, f, k){ 
          var sum_a, sum_b, x1, y1, t;
          var m = X.A.length;
          var n = X.A[0].length;
          var A = new Array(m);
          var B = new Array(m);
          for(var i = 0; i &lt; m; i++){
            A[i] = new Array(n);
            B[i] = new Array(n);
          }        
          for(var x = 0; x &lt; m; x++) {
            for(var y = 0; y &lt; n; y++){
              sum_a = 0.0;
              sum_b = 0.0;
              for(var i = -1; i &lt;= 1; i++){
                for(var j = -1; j &lt;= 1; j++){
                  x1 = subm_index(m, x - i);
                  y1 = subm_index(n, y - j);
                  sum_a = sum_a + L[i+1][j+1] * X.A[x1][y1];
                  sum_b = sum_b + L[i+1][j+1] * X.B[x1][y1];
                }
              }
              t = X.A[x][y]*X.B[x][y]*X.B[x][y];
              A[x][y] = X.A[x][y] + DA*sum_a - t + f*(1-X.A[x][y]);
              B[x][y] = X.B[x][y] + DB*sum_b + t - (k+f)*X.B[x][y];
            }
          }
          return {A: A, B: B};
        }
        function iterate_Gray_Scott(X, L, DA, DB, f, k, n){
          for(var i = 0; i &lt; n; i++){
            X = update_concentrations(X, L, DA, DB, f, k); 
          }
          return X;
        }
        var L = [[0.05, 0.2, 0.05], [0.2, -1, 0.2], [0.05, 0.2, 0.05]];
        var DA = 1;
        var DB = 0.5;
        var f = 0.0545;
        var k = 0.062;
      &lt;/script&gt;
  
      &lt;script type="text/paperscript" canvas="quad"&gt;
        var pixels = 50;
        var gridSize = 2;
        var rectSize = 2;
        var A = new Array(pixels);
        var B = new Array(pixels);
        var Paths = new Array(pixels);
        for(var i = 0; i &lt; pixels; i++){
          A[i] = new Array(pixels);
          B[i] = new Array(pixels);
          Paths[i] = new Array(pixels);
          for(var j = 0; j &lt; pixels; j++){
            A[i][j] = 1;
            B[i][j] = Math.random() &lt; 0.99 ? 0 : 1;
          }
        }
        var X = {A: A, B: B};
  
        var nframes = 50;
  
        var XX = new Array(nframes);
        XX[0] = X;
        for(var frm = 1; frm &lt; nframes; frm++){
          XX[frm] = iterate_Gray_Scott(XX[frm-1], L, DA, DB, f, k, frm);
        }
        
        var Rects = [];
        for(var x = 0; x &lt; pixels; x++){
          for(var y = 0; y &lt; pixels; y++){
            var rect = new Path.Rectangle(new Point(x, y) * gridSize, new Size(rectSize, rectSize));
            var color = {
              hue: 1,
              saturation: 1,
              brightness: 1
            };
            rect.fillColor = color;
            rect.visible = false;
            Rects.push(rect);
          }
        }
  
        group = new Group(Rects);
  
        symbolGroup = new Symbol(group);
  
        var Groups = new Array(nframes);
        for(var frm = 0; frm &lt; nframes; frm++){
          Groups[frm] = symbolGroup.place(view.center);
          var k = 0;
          for(var x = 0; x &lt; pixels; x++){
            for(var y = 0; y &lt; pixels; y++){
              Groups[frm].definition.definition.children[k].fillColor = {
                hue: XX[frm].B[x][y] * 360,
                saturation: 1,
                brightness: 1
              };
              k = k+1;
            }
          } 
          XX[frm] = null; // to free some memory
        } 
  
        project.activeLayer.position = view.center;
  
        function onFrame(event){
          if(event.count &lt; nframes){
            console.log(event.count);
            Groups[event.count].visible = true;
            if(event.count &gt; 0){
              Groups[event.count-1].visible = false; // to free some memory
            }
          }
        }
      &lt;/script&gt;
  
      &lt;canvas id="quad" resize&gt;&lt;/canvas&gt;
    &lt;/body&gt;
  &lt;/html&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>Can you help me to fix this last code?</p>