Temporal Programming, a new name for an old paradigm
Why wait for a language; here is a macro:<p>Firstly, we define a place (temporal x y) such that when this place is accessed, it denotes x, and when it is assigned, the assignment goes to y:<p><pre><code>  (defplace (temporal-place var var*) body
    (getter setter
      ^(macrolet ((,getter () ,var)
                  (,setter (val) ^(set ,&#x27;,var* ,val)))
         ,body))
    (setter
      ^(macrolet ((,setter (val) ^(set ,&#x27;,var* ,val)))
         ,body)))

  (define-place-macro temporal (var var*) ^(temporal-place ,var ,var*))

  (defmacro temporal (var var*) var)
</code></pre>
We can then use that as a building block whereby we define an apparent variable v as a symbol macro which expands to (temporal vold vnew).  All accesses to v get the value of vold, but assignments to v do not affect vold; they go to vnew.<p>Here is a let-like macro which sets up the specified variable as temporal. The initial values propagate into both the old and new location.<p>Then before the last form of the body is evalulated, the new values are copied to the old values.<p><pre><code>  (defmacro temporal-let (vars . body)
    (let ((olds (mapcar (ret (gensym)) vars))
          (news (mapcar (ret (gensym)) vars)))
      ^(let* (,*(zip olds [mapcar cadr vars])
              ,*(zip news olds))
         (symacrolet ,(zip [mapcar car vars]
                           [mapcar (op list &#x27;temporal) olds news])
           ,*(butlast body)
           (set ,*(weave olds news))
           ,*(last body)))))

</code></pre>
Test. e.g:<p><pre><code>  1&gt; (temporal-let ((x 1) (y 2))
        (set x y)
        (set y x)
        (list x y))
  (2 1)
</code></pre>
The expansion is:<p><pre><code>  2&gt; (expand &#x27;(temporal-let ((x 1) (y 2))
        (set x y)
        (set y x)
        (list x y)))
  (let* ((#:g0024 1)
         (#:g0025 2)
         (#:g0026 #:g0024)
         (#:g0027 #:g0025))
    (sys:setq #:g0026
      #:g0025)
    (sys:setq #:g0027
      #:g0024)
    (progn (sys:setq #:g0024
             #:g0026)
      (sys:setq #:g0025
        #:g0027))
    (list #:g0024 #:g0025))
</code></pre>
Let&#x27;s see how it compiles:<p><pre><code>  2&gt; (disassemble (compile-toplevel &#x27;(temporal-let ((x 1) (y 2))
        (set x y)
        (set y x)
        (list x y))))
  data:
      0: 1
      1: 2
  syms:
      0: list
  code:
      0: 20020002 gcall t2 0 d1 d0
      1: 04010000
      2: 00000400
      3: 10000002 end t2
  instruction count:
      2
  #&lt;sys:vm-desc: 903ec50&gt;
</code></pre>
Oops, it got compiled to a single call instruction invoking (list 2 1). Let&#x27;s try <i>opt-level</i> zero:<p><pre><code>  1&gt; (let ((*opt-level* 0))
       (disassemble (compile-toplevel &#x27;(temporal-let ((x 1) (y 2))
         (set x y)
         (set y x)
         (list x y)))))
  data:
      0: 1
      1: 2
  syms:
      0: list
  code:
      0: 04020004 frame 2 4
      1: 2C800400 movsr v00000 d0
      2: 2C810401 movsr v00001 d1
      3: 2C820800 movsr v00002 v00000
      4: 2C830801 movsr v00003 v00001
      5: 2C820801 movsr v00002 v00001
      6: 2C830800 movsr v00003 v00000
      7: 2C800802 movsr v00000 v00002
      8: 2C810803 movsr v00001 v00003
      9: 20020002 gcall t2 0 v00000 v00001
     10: 08000000
     11: 00000801
     12: 10000002 end t2
     13: 10000002 end t2
  instruction count:
     12
  #&lt;sys:vm-desc: 9de1b50&gt;
</code></pre>
TXR Lisp&#x27;s compiler performs frame elimination optimization whereby the v registers get reassigned to t registers, eliminating the frame setup. The t registers are subject to some decent data flow optimizations and can disappear entirely, like in this case.