As we are familiar, DATE! can have a TIME! component:
>> d: now
== 21-Nov-2021/18:56:45-5:00
>> type of d
== #[datatype! date!]
>> t: d.time
== 18:56:45
>> type of t
== #[datatype! time!]
Although TIME! can exist as a separate cell and value type, a DATE! doesn't store a time cell inside of it. It packs the date and time information into a single cell.
Hence when you say d.time above, a new TIME! value has to be synthesized. There's not a whole cell worth of time to hand a pointer back to...its woven into the bits of the DATE!.
That might not sound like much of an issue, but it creates the problem I refer to as "sub-cell addressing".
If you've missed everything I've griped about with this so far, it means that when you want to see a behavior like the following:
>> d.time.hour: 12
== 12
>> date
== 21-Nov-2021/12:56:45-5:00 ; we want hour updated
We run into the problem that if d.time synthesizes a value, then a naive picking process of (d.time).hour: 12 would only be able to manipulate the bits in the synthesized time. That wouldn't change d. What the user actually wanted was to update the bits of a time that was folded into the implementation of the date.
Rebol Lacks The Vocabulary To Do This In An Obvious Way
The smallest units that Rebol speaks in terms of are the cell
and the node
.
(If you need a refresher on these, my conference video tech talk explains them.)
It would appear we could be able to simplify matters if we changed the combination of DATE! and TIME! to point to a 2-cell node.
DATETIME! cell
[ ] DATE! TIME!
--> points to [ 21-Nov-2021 | 18:56:45-5:00 ] (2 cells)
(Whether the "zone" is part of a time or lives in the datetime would depend on whether you wanted to write d.zone: -5:00
or d.time.zone: -5:00
, I don't know if it ever makes sense to speak of a time with a zone independent of a datetime or not.)
Breaking things up this way, we can say that d.time implicates a cell. And we can have some operation that acts on a cell (let's say POKE) like:
>> poke 18:56:45 'hour 12
== 12:56:45
Hang On: DATE!, TIME! (and DATETIME!) are IMMEDIATE!
We still have a bit of a problem here with our smallest units of representation. Presumably we don't want this:
>> d1: 21-Nov-2021/18:56:45-5:00
>> d2: d1
>> d1.time.hour: 12
== 12
>> d1
== 21-Nov-2021/12:56:45-5:00
>> d2
== 21-Nov-2021/12:56:45-5:00 ; don't want d2 to change (right?)
But we also don't want to be needlessly copying the 2-cell node each time a date is assigned. So it would be a copy-on-write mechanic.
If we're working with a cell-based granularity, then we wind up in a somewhat similar situation to what we had before...where the tuple processing has to propagate backwards. e.g. when you have the POKE that changes the cell bits for the TIME! to make a new TIME! cell, there has to be some memory going back to the DATETIME! in order to tell it to make a new node and write the cell into the copy.
Does framing this in terms of cells offer any benefit over letting the DATETIME! be a higher-level entity that does a more specific folding of the TIME! cell into its bits? This is a question I've been trying to answer, and haven't had an easy time of answering.
One thing it would do to use a cell-based protocol is that it could generalize properties that had flags on cells, such as being PROTECT'ed. Without the picking protocol requiring each step to go through a cell, the system cannot fiddle these bits in a known way. So just as the DATE! folds the TIME! into it in some arbitrary way, the protect bit would have to go through this through a complex protocol also.
What I do know is that my current generalized solution is rather complex and slow--and doesn't answer how to do things like PROTECT. We're seeing a slowdown from many different angles and I am trying to figure out what the best tradeoff is in terms of simplicity and generality. It's not easy.