Mutate-immutable-arrays-in-javascript: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
[[Category:HowTo]]<br />In my work with QML, I needed a way to mutate an immutable array. It's surprisingly easy to do this in Javascript. In this article, I give an outline of the technique followed by working Javascript code.
[[Category:HowTo]]
In my work with QML, I needed a way to mutate an immutable array. It's surprisingly easy to do this in Javascript. In this article, I give an outline of the technique followed by working Javascript code.


[toc align_right=“yes” depth=“3”]
[toc align_right=“yes” depth=“3”]
Line 7: Line 8:
== Variables ==
== Variables ==


Let S, A, and I be zero-based arrays.<br />Let A be an immutable array<br />Let I be empty<br />Let N be an integer with initial value 0
Let S, A, and I be zero-based arrays.
Let A be an immutable array
Let I be empty
Let N be an integer with initial value 0


Let S[i]=i+1 for all i in {0..||A||}
Let S[i]=i+1 for all i in {0..||A||}


Let a positive value in S indicate an element of A:<br /> S[i] indicates A[S[i] - 1].
Let a positive value in S indicate an element of A:
S[i] indicates A[S[i] - 1].


Let a negative value in S indicate an element of I:<br /> S[i] indicates I[<s>S[i]</s> 1]
Let a negative value in S indicate an element of I:
S[i] indicates I[-S[i]- 1]


S is the mutable &quot;face&amp;quot; of A.
S is the mutable "face" of A.


Let N indicate the next unused element of I.
Let N indicate the next unused element of I.
Line 21: Line 27:
== Pseudocode ==
== Pseudocode ==


To insert an object X into S at index i:<br /><code><br />S.splice(i, 0, <s><span class="N+1"><br />I[N]=X<br />N=N+1<br /></code><br />To remove an object from S at index i:<br /><code><br />I[i]=undefined<br />S.splice(i, 1)<br /></code>
To insert an object X into S at index i:
<br />To change an the object at S[i] to X:<br /><code><br />if S[i] &gt; 0:<br /> S[i]=</span></s>(N+1)<br /> I[N]=X<br /> N=N+1<br />else:<br /> I[<s>S[i]</s> 1]=X<br /></code>
<code>
S.splice(i, 0, -<span class="N+1">
I[N]=X
N=N+1
</code>
To remove an object from S at index i:
<code>
I[i]=undefined
S.splice(i, 1)
</code>


The value of S[i] is<br /><code><br /> A[S[i] - 1] if S[i] &gt; 0<br /> I[<s>S[i]</s> 1] otherwise<br /></code>
To change an the object at S[i] to X:
<code>
if S[i] > 0:
S[i]=</span>-(N+1)
I[N]=X
N=N+1
else:
I[-S[i]- 1]=X
</code>
 
The value of S[i] is
<code>
A[S[i] - 1] if S[i] > 0
I[-S[i]- 1] otherwise
</code>


== Bugs? ==
== Bugs? ==
Line 32: Line 61:
= The Code =
= The Code =


This code assumes<br /><code><br />// A is the unmutable array<br />var A
This code assumes
<code>
// A is the unmutable array
var A


// S is the mutable face of A.<br />// You must initialize S as described in the outline<br />var S=new Array()
// S is the mutable face of A.
// You must initialize S as described in the outline
var S=new Array()


// I contains the values you insert<br />// or change in A and its mutable face.<br />var I=new Array()
// I contains the values you insert
// or change in A and its mutable face.
var I=new Array()


// N is the index of the next element of S.<br />var N=0<br /></code><br /><code><br />function get(i)<br />{<br /> return (S[i] &gt; 0) ? A[S[i] - 1] : I[<s>S[i]</s> 1]<br />}<br /></code><br /><code><br />function insert(i, j)<br />{<br /> S.splice(i, 0, <s><span class="N+1">)<br /> I[N]=j<br /> N++<br />}<br /></code><br /><code><br />function remove(i)<br />{<br /> I[i]=undefined<br /> S.splice(i, 1)<br />}<br /></code><br /><code><br />function set(i,j)<br />{<br /> if (S[i] &gt; 0) {<br /> S[i]=</span></s>(N+1)<br /> I[N]=j<br /> N++<br /> }<br /> else<br /> {<br /> I[<s>S[i]</s> 1]=j<br /> }<br />}<br /></code>
// N is the index of the next element of S.
var N=0
</code>
<code>
function get(i)
{
return (S[i] > 0) ? A[S[i] - 1] : I[-S[i]- 1]
}
</code>
<code>
function insert(i, j)
{
S.splice(i, 0, -<span class="N+1">)
I[N]=j
N++
}
</code>
<code>
function remove(i)
{
I[i]=undefined
S.splice(i, 1)
}
</code>
<code>
function set(i,j)
{
if (S[i] > 0) {
S[i]=</span>-(N+1)
I[N]=j
N++
}
else
{
I[-S[i]- 1]=j
}
}
</code>

Revision as of 10:50, 25 February 2015

In my work with QML, I needed a way to mutate an immutable array. It's surprisingly easy to do this in Javascript. In this article, I give an outline of the technique followed by working Javascript code.

[toc align_right=“yes” depth=“3”]

The Outline

Variables

Let S, A, and I be zero-based arrays. Let A be an immutable array Let I be empty Let N be an integer with initial value 0

Let S[i]=i+1 for all i in {0..||A||}

Let a positive value in S indicate an element of A:

S[i] indicates A[S[i] - 1].

Let a negative value in S indicate an element of I:

S[i] indicates I[-S[i]- 1]

S is the mutable "face" of A.

Let N indicate the next unused element of I.

Pseudocode

To insert an object X into S at index i:

S.splice(i, 0, -<span class="N+1">
I[N]=X
N=N+1

To remove an object from S at index i:

I[i]=undefined
S.splice(i, 1)

To change an the object at S[i] to X:

if S[i] > 0:
 S[i]=</span>-(N+1)
 I[N]=X
 N=N+1
else:
 I[-S[i]- 1]=X

The value of S[i] is

 A[S[i] - 1] if S[i] > 0
 I[-S[i]- 1] otherwise

Bugs?

It may be possible for I to grow without bound.

The Code

This code assumes

// A is the unmutable array
var A

// S is the mutable face of A.
// You must initialize S as described in the outline
var S=new Array()

// I contains the values you insert
// or change in A and its mutable face.
var I=new Array()

// N is the index of the next element of S.
var N=0
function get(i)
{
 return (S[i] > 0) ? A[S[i] - 1] : I[-S[i]- 1]
}
function insert(i, j)
{
 S.splice(i, 0, -<span class="N+1">)
 I[N]=j
 N++
}
function remove(i)
{
 I[i]=undefined
 S.splice(i, 1)
}
function set(i,j)
{
 if (S[i] > 0) {
 S[i]=</span>-(N+1)
 I[N]=j
 N++
 }
 else
 {
 I[-S[i]- 1]=j
 }
}