Open IngoHohmann opened 8 years ago
We've discussed how the PAIR! change to permit any two values has a number of nice properties (not the least of which is preserving the precision of the integers or floats/decimals put in.)
It might be that having PAIR! stay immediate offers something that one can't get with a series of size 2, which could be a "feature". I don't know that I have any particular religion about this subject. The implementation is certainly not geared up at this time to make things that are larger than just a value cell act as immediates...e.g. REBVALs are copied just by their raw bits. So if there are any pointers in those REBVALs, they are raw bit copied...hence two pairs will share the same pointer to the two-value-cell series.
The only thing I'm pretty dead set on is not having a third type of half-cell number that is made especially for pairs. That's bad. And copying values may need to be done "live" instead of with *dest = *src;
assignments anyway (relative values already must, anyway). That live moment could be a chance to do an if (immediate) test and hook it.
I guess I just wanted to see what happened. So chime in with any thoughts.
We now actually do have the described hook point instead of just *dest = *src
(called Move_Value()
). This gives the power to create forms of immediates that don't (always) fit entirely into a cell. We might imagine such a hook being used for arbitrary-precision integers, for instance... if the integer fits into the cell it gets copied just as the payload bits, if it doesn't then you need a new identity established for what the payload references that doesn't fit in the cell, so changes to that indirect payload from the copy do not affect the original.
The thing that bugged me about the old definition is that it was creating new kinds of integers and floats that affected the user. They were losing precision, and it added whole new categories of math to the system...which was not good. We have enough trouble defining INTEGER! and FLOAT!/DECIMAL! as is, without defining HALF-INTEGER! and HALF-FLOAT!. So I like the decision to make whatever implementation choice here not introduce new number types.
Yet if we copied every pair on every Move_Value(), that makes one REBSER-sized unit (a "pairing" node). The memory usage is inconsequential, the real impact is on the number of things the GC would have to be looping over if you have some pathological case. I guess we'd have to know how bad it is.
I don't mind us bringing back a certain kind of PAIR! that fits into a REBVAL, e.g. to have PAIR_FLAG_FITS_IN_CELL, and use that for something like 1x1 which wouldn't require two 64-bit integers. This would cover some pairs. It's easy to tell when the integer case would lose precision, harder for the floating point case.
I've been thinking that FIND in a MAP! might return a PAIR! with the key and the value, and though I've thought it might be interesting to have that be non-immediate and let you poke into the internals of the map, it may force the implementation of MAP! too much to be an index over PAIR!s, which has some advantages but some disadvantages. If it were immediate, then it might be returned by OBJECT! as well.