@@ -1346,32 +1346,34 @@ func ArrayTerm(a ...*Term) *Term {
13461346// NewArray creates an Array with the terms provided. The array will
13471347// use the provided term slice.
13481348func NewArray (a ... * Term ) * Array {
1349- hs := make ([]int , len (a ))
1350- for i , e := range a {
1351- hs [i ] = e .Value .Hash ()
1349+ arr := & Array {
1350+ elems : a ,
1351+ ground : termSliceIsGround (a ),
1352+ hashValid : false , // hash will be computed on first access
13521353 }
1353- arr := & Array {elems : a , hashs : hs , ground : termSliceIsGround (a )}
1354- arr .rehash ()
13551354 return arr
13561355}
13571356
13581357// Array represents an array as defined by the language. Arrays are similar to the
13591358// same types as defined by JSON with the exception that they can contain Vars
13601359// and References.
1360+ //
1361+ // Optimization: removed hashs []int slice to save memory (8*N bytes per array).
1362+ // Hash is now computed lazily on first access and cached in hashValid flag.
13611363type Array struct {
1362- elems []* Term
1363- hashs [] int // element hashes
1364- hash int
1365- ground bool
1364+ elems []* Term
1365+ hash int
1366+ ground bool
1367+ hashValid bool // true if hash is up-to-date
13661368}
13671369
13681370// Copy returns a deep copy of arr.
13691371func (arr * Array ) Copy () * Array {
13701372 return & Array {
1371- elems : termSliceCopy (arr .elems ),
1372- hashs : slices . Clone ( arr .hashs ) ,
1373- hash : arr .hash ,
1374- ground : arr .ground ,
1373+ elems : termSliceCopy (arr .elems ),
1374+ hash : arr .hash ,
1375+ ground : arr .ground ,
1376+ hashValid : arr .hashValid ,
13751377 }
13761378}
13771379
@@ -1460,12 +1462,24 @@ func (arr *Array) Sorted() *Array {
14601462 slices .SortFunc (cpy , TermValueCompare )
14611463
14621464 a := NewArray (cpy ... )
1463- a .hashs = arr .hashs
1465+ // If parent arr already has valid hash, copy it since sorting doesn't change hash
1466+ if arr .hashValid {
1467+ a .hash = arr .hash
1468+ a .hashValid = true
1469+ }
14641470 return a
14651471}
14661472
14671473// Hash returns the hash code for the Value.
1474+ // Computes hash lazily on first access and caches it.
14681475func (arr * Array ) Hash () int {
1476+ if ! arr .hashValid {
1477+ arr .hash = 0
1478+ for _ , e := range arr .elems {
1479+ arr .hash += e .Value .Hash ()
1480+ }
1481+ arr .hashValid = true
1482+ }
14691483 return arr .hash
14701484}
14711485
@@ -1515,20 +1529,16 @@ func (arr *Array) Set(i int, v *Term) {
15151529 arr .set (i , v )
15161530}
15171531
1518- // rehash updates the cached hash of arr .
1532+ // rehash invalidates the cached hash so it will be recomputed on next access .
15191533func (arr * Array ) rehash () {
1520- arr .hash = 0
1521- for _ , h := range arr .hashs {
1522- arr .hash += h
1523- }
1534+ arr .hashValid = false
15241535}
15251536
15261537// set sets the element i of arr.
15271538func (arr * Array ) set (i int , v * Term ) {
15281539 arr .ground = arr .ground && v .IsGround ()
15291540 arr .elems [i ] = v
1530- arr .hashs [i ] = v .Value .Hash ()
1531- arr .rehash ()
1541+ arr .rehash () // invalidate hash cache
15321542}
15331543
15341544// Slice returns a slice of arr starting from i index to j. -1
@@ -1537,21 +1547,20 @@ func (arr *Array) set(i int, v *Term) {
15371547// the other.
15381548func (arr * Array ) Slice (i , j int ) * Array {
15391549 var elems []* Term
1540- var hashs []int
15411550 if j == - 1 {
15421551 elems = arr .elems [i :]
1543- hashs = arr .hashs [i :]
15441552 } else {
15451553 elems = arr .elems [i :j ]
1546- hashs = arr .hashs [i :j ]
15471554 }
15481555 // If arr is ground, the slice is, too.
15491556 // If it's not, the slice could still be.
15501557 gr := arr .ground || termSliceIsGround (elems )
15511558
1552- s := & Array {elems : elems , hashs : hashs , ground : gr }
1553- s .rehash ()
1554- return s
1559+ return & Array {
1560+ elems : elems ,
1561+ ground : gr ,
1562+ hashValid : false , // hash will be computed lazily
1563+ }
15551564}
15561565
15571566// Iter calls f on each element in arr. If f returns an error,
@@ -1581,9 +1590,14 @@ func (arr *Array) Foreach(f func(*Term)) {
15811590func (arr * Array ) Append (v * Term ) * Array {
15821591 cpy := * arr
15831592 cpy .elems = append (arr .elems , v )
1584- cpy .hashs = append (arr .hashs , v .Value .Hash ())
1585- cpy .hash = arr .hash + v .Value .Hash ()
15861593 cpy .ground = arr .ground && v .IsGround ()
1594+ // If hash was already computed, we can update it incrementally
1595+ if arr .hashValid {
1596+ cpy .hash = arr .hash + v .Value .Hash ()
1597+ cpy .hashValid = true
1598+ } else {
1599+ cpy .hashValid = false // will be computed on first access
1600+ }
15871601 return & cpy
15881602}
15891603
0 commit comments