[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
## mutable considered harmful, Range edition

**From**: |
John W. Eaton |

**Subject**: |
mutable considered harmful, Range edition |

**Date**: |
Tue, 9 Jun 2020 00:11:05 -0400 |

**User-agent**: |
Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.8.1 |

When using --traditional, I noticed that the result of
zeros (1, 0)
was [](0x0) instead of [](1x0).

`This error is related to the use of a mutable cache value in the Range
``data type. Here's how:
`

`Constant row vectors (like those produced by zeros and ones) are stored
``as ranges with the number of elemnts set to the number of columns and
``the increment set to zero.
`

`But using --traditional implies "disable_range (true)" so the
``Range::matrix_value method is called is called in the octave_value
``constructor and that appears to fail. If I understand correctly, the
``matrix_value method returns the incorrect result because it is declared
``const but also modifies and returns a mutable value (the cached Matrix
``value). The compiler appears to be choosing to return the cache value
``before it is modified (the method is const, so normally it wouldn't
``change any member variables).
`

`Is it possible to make the mutable cache value reliable in situations
``like this? If not, then this appears to be another example of why we
``need to eliminate mutable in most places in Octave.
`

`Separately, I see that other than the Range::matrix_value method, we set
``the cache value in the operators, like this:
`
Range operator + (const Range& r, double x)
{
Range result (r.base () + x, r.limit () + x, r.inc (), r.numel ());
if (result.m_numel < 0)
result.m_cache = r.matrix_value () + x;
return result;
}

`As I recall, setting the cache in these functions (and not just the
``matrix_value method) is done so that, for example, adding a constant to
``a range and then converting to a matrix will produce exactly the same
``result as converting a range to a matrix and then adding a constant to
``the matrix (in psuedo code):
`
matrix (r) + c == matrix (r + c)

`Using the cache this way does avoid the cost of any repeated conversions
``to a matrix value, but it also forces the cache to be created for any
``operation on a range, not just the result. So it largely defeats the
``purpose of the efficient range object storage, and I'm wondering whether
``it is worth having a special range data type at all? What do we really
``gain for the additional complexity?
`
jwe

**mutable considered harmful, Range edition**,
*John W. Eaton* **<=**