Date: Thu, 17 Sep 2020 20:50:10 -0700
From: Bret Victor
Subject: memories
I found myself writing "persistent state" too persistently yesterday, so it was time to make some memories.

It's the "sticky statements" approach to state, slightly different but similar to what is shown in the prototype video.

    Remember (you) is a "dog".

makes the statement:  (you) remembers (you) is a "dog".

Unlike Claim or Wish, this statement doesn't appear until the beginning of the next tick, and it remains until explicitly forgotten:

    Forget (you) is a "dog".

Match this statement just like you match a wish:

    When /someone/ remembers /dog/ is a "dog":


Only

Often, you want a memory to update some previous memory.  For example, this is a problem:

    Remember (you) has (6) cupcakes.  (later followed by)
    Remember (you) has (7) cupcakes.

You end up with two separate statements, remembering you have both 6 and 7 cupcakes.  Use "only" to specify which arguments are the "variable slots":

    Remember (you) has (only 6) cupcakes.  (later followed by)
    Remember (you) has (only 7) cupcakes.

The second memory replaces the first, and you end up with only 7 cupcakes.

In usage so far, I've almost always forgotten to write the "only" (resulting in memories piling up), but maybe we'll get used to it, or maybe it'll have to change.  I don't have any better ideas.


Forgetting

You can forget a pattern:

    Forget (you) has /n/ cupcakes.

or even

    Forget /someone/ has /n/ cupcakes.

It is not an error to forget something that isn't there.


Initializing

Here is a counter:

    When /someone/ remembers (you) has count /n or 0/:
        Wish (you) is labelled (n).
        Remember (you) has count (only n+1).
    End

Note the /n or 0/ to get started with a default value.  Default values should hopefully replace the need for initialized state in most cases.  If you really need to initialize, you can do it explicitly:

    When /nobody/ remembers (you) has count /something/:
        Remember (you) has count (only 0).
    End


When unmatched

This state is persistent.  If you remove the counter and put it back, it will continue counting where it left off.  If you want to reset when removed, here's a way:

    When unmatched:
        Forget (you) has count /n/.
    End

That is, Remember and Forget (unlike Claim and Wish) are useful within "When unmatched".

In a normal context (not within "When unmatched"), Remember and Forget generate wishes, which means they are nullified if an error occurs.


C

Memories work just fine in C.  Notice the "only" goes before the type:

    // Counter in C
    When /someone/ remembers (you) has count /int n or 0/:
        Wish (you) is labelled (n).
        Remember (you) has count (only (int)n+1).
    End


Implementation

Two pages in Time Kit, each around 50 lines.  Like nothing!

    32665, -- Memories
    32664, -- Memory macros