Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,2 @@
---
from: http://rosettacode.org/wiki/History_variables

View file

@ -0,0 +1,24 @@
''Storing the history of objects in a program is a common task.
Maintaining the history of an object in a program has traditionally required programmers either to write specific code for handling the historical data, or to use a library which supports history logging.''
''History variables are variables in a programming language which store not only their current value, but also the values they have contained in the past. Some existing languages do provide support for history variables. However these languages typically have many limits and restrictions on use of history variables.
''
[http://www.bod.com/index.php?id=3435&objk_id=148050 "History Variables:
The Semantics, Formal Correctness, and Implementation of History Variables
in an Imperative Programming Language" by Mallon and Takaoka]
Concept also discussed on [http://lambda-the-ultimate.org/node/3111 LtU] and [http://www.patents.com/us-7111283.html Patents.com].
;Task:
Demonstrate History variable support:
* enable history variable support (if needed)
* define a history variable
* assign three values
* non-destructively display the history
* recall the three values.
<br>For extra points, if the language of choice does not support history variables,
demonstrate how this might be implemented.
<br><br>

View file

@ -0,0 +1,21 @@
HistoryVar equ $100200 ;assume this is work ram.
LEA HistoryVar+4,A0
MOVE.L #$11223344,D0
MOVE.L D0,-(A0) ;store the 32-bit value #$11223344 starting at $100200
MOVE.L #$55667788,D0
MOVE.L D0,-(A0) ;store the 32-bit value #$5566788 at $1001FC
MOVE.L #$AABBCCDD,D0
MOVE.L D0,-(A0) ;store the 32-bit value #$AABBCCDD at $1001F8
;display the history
LEA HistoryVar,A0
MOVE.L (A0),D0 ;load #$11223344 into D0
MOVE.L (-4,A0),D1 ;load #$55667788 into D1
MOVE.L (-8,A0),D2 ;load #$AABBCCDD into D2
jsr PrintHex32 ;unimplemented routine that prints D0 as a 32-bit hex number
mov D1,D0
jsr PrintHex32
mov D2,D0
jsr PrintHex32

View file

@ -0,0 +1,35 @@
begin
% implements integer history variables %
% similar history types could be defined for other types of variable %
record HInteger ( integer iValue; reference(HInteger) iPrev );
% sets the latest value of hv to n %
procedure setIhv ( reference(HInteger) value result hv; integer value n ) ; hv := HInteger( n, hv );
% declare an integer history variable %
reference(HInteger) hv;
% initialise the history to a null value %
hv := null;
% assign three values %
setIhv( hv, 1 );
setIhv( hv, 2 );
setIhv( hv, 3 );
% show the history of hv %
begin
reference(HInteger) h;
write( "hv history: " );
h := hv;
while h not = null do begin
writeon( i_w := 3, s_w := 0, iValue(h), " " );
h := iPrev(h)
end while_h_ne_null
end;
% remove the values from hv, summing them as in the Ada sample %
begin
integer s;
s := 0;
while hv not = null do begin
s := s + iValue(hv);
hv := iPrev(hv)
end while_hv_ne_null ;
write( "Sum of the historic values: ", s )
end
end.

View file

@ -0,0 +1,34 @@
private with Ada.Containers.Indefinite_Vectors;
generic
type Item_Type (<>) is private;
package History_Variables is
type Variable is tagged limited private;
-- set and get current value
procedure Set(V: in out Variable; Item: Item_Type);
function Get(V: Variable) return Item_Type;
-- number of items in history (including the current one)
function Defined(V: Variable) return Natural;
-- non-destructively search for old values
function Peek(V: Variable; Generation: Natural := 1) return Item_Type;
-- V.Peek(0) returns current value; V.Peek(1) the previous value, etc.
-- when calling V.Peek(i), i must be in 0 .. V.Defined-1, else Constraint_Error is raised
-- destructively restore previous value
procedure Undo(V: in out Variable);
-- old V.Peek(0) is forgotten, old V.Peek(i) is new V.Peek(i-1), etc.
-- accordingly, V.Defined decrements by 1
-- special case: if V.Defined=0 then V.Undo does not change V
private
package Vectors is new Ada.Containers.Indefinite_Vectors
(Index_Type => Positive,
Element_Type => Item_Type);
type Variable is tagged limited record
History: Vectors.Vector;
end record;
end History_Variables;

View file

@ -0,0 +1,35 @@
package body History_Variables is
-- set and get
procedure Set(V: in out Variable; Item: Item_Type) is
begin
V.History.Prepend(Item);
end Set;
function Get(V: Variable) return Item_Type is
begin
return V.History.First_Element;
end Get;
-- number of items in history (including the current one)
function Defined(V: Variable) return Natural is
begin
return (1 + V.History.Last_Index) - V.History.First_Index;
end Defined;
-- non-destructively search
function Peek(V: Variable; Generation: Natural := 1) return Item_Type is
Index: Positive := V.History.First_Index + Generation;
begin
if Index > V.History.Last_Index then
raise Constraint_Error;
end if;
return V.History.Element(Index);
end Peek;
procedure Undo(V: in out Variable) is
begin
V.History.Delete_First;
end Undo;
end History_Variables;

View file

@ -0,0 +1,32 @@
with Ada.Text_IO, History_Variables;
procedure Test_History is
package Int_With_Hist is new History_Variables(Integer);
-- define a history variable
I: Int_With_Hist.Variable;
Sum: Integer := 0;
begin
-- assign three values
I.Set(3);
I.Set(I.Get + 4);
I.Set(9);
-- non-destructively display the history
for N in reverse 0 .. I.Defined-1 loop
Ada.Text_IO.Put(Integer'Image(I.Peek(N)));
end loop;
Ada.Text_IO.New_Line;
-- recall the three values
while I.Defined > 0 loop
Sum := Sum + I.Get;
I.Undo;
end loop;
Ada.Text_IO.Put_Line(Integer'Image(Sum));
end Test_History;

View file

@ -0,0 +1,32 @@
with Ada.Text_IO, History_Variables;
procedure Test_History is
package Str_With_Hist is new History_Variables(String);
-- define a history variable
S: Str_With_Hist.Variable;
Sum: Integer := 0;
begin
-- assign three values
S.Set("one");
S.Set(S.Get & S.Get); --"oneone"
S.Set("three");
-- non-destructively display the history
for N in reverse 0 .. S.Defined-1 loop
Ada.Text_IO.Put(S.Peek(Generation => N) &" ");
end loop;
Ada.Text_IO.New_Line;
-- recall the three values
while S.Defined > 0 loop
Sum := Sum + S.Get'Length;
S.Undo;
end loop;
Ada.Text_IO.Put_Line(Integer'Image(Sum));
end Test_History;

View file

@ -0,0 +1,45 @@
define :history [][
init: [
this\record: @[0]
]
]
assign: function [historyVar,newValue][
historyVar\record: historyVar\record ++ newValue
]
alias.infix {'-->} 'assign
records: function [historyVar][
historyVar\record
]
retrieve: function [historyVar][
result: last historyVar\record
historyVar\record: chop historyVar\record
return result
]
current: function [historyVar][
return last historyVar\record
]
do [
h: to :history []
print "Assigning three values: 1, 2, 3..."
h --> 1
h --> 2
h --> 3
print "\nHistory (oldest values first):"
print [">" records h]
print ["\nCurrent value is:" current h]
print "\nRecalling the three values..."
loop 1..3 'x ->
print ["- Recalled:" retrieve h]
print "\nHistory:"
print [">" records h]
]

View file

@ -0,0 +1,29 @@
public class HistoryVariable
{
private Object value;
public HistoryVariable(Object v)
{
value = v;
}
public void update(Object v)
{
value = v;
}
public Object undo()
{
return value;
}
@Override
public String toString()
{
return value.toString();
}
public void dispose()
{
}
}

View file

@ -0,0 +1,43 @@
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
public privileged aspect HistoryHandling
{
before() : execution(HistoryVariable.new(..))
{
history.put((HistoryVariable) thisJoinPoint.getTarget(), new LinkedList<>());
}
after() : execution(void HistoryVariable.dispose())
{
history.remove(thisJoinPoint.getTarget());
}
before(Object v) : execution(void HistoryVariable.update(Object)) && args(v)
{
final HistoryVariable hv = (HistoryVariable) thisJoinPoint.getThis();
history.get(hv).add(hv.value);
}
after() : execution(Object HistoryVariable.undo())
{
final HistoryVariable hv = (HistoryVariable) thisJoinPoint.getThis();
final Deque<Object> q = history.get(hv);
if (!q.isEmpty())
hv.value = q.pollLast();
}
String around() : this(HistoryVariable) && execution(String toString())
{
final HistoryVariable hv = (HistoryVariable) thisJoinPoint.getThis();
final Deque<Object> q = history.get(hv);
if (q == null)
return "<disposed>";
else
return "current: "+ hv.value + ", previous: " + q.toString();
}
private Map<HistoryVariable, Deque<Object>> history = new HashMap<>();
}

View file

@ -0,0 +1,17 @@
public final class Main
{
public static void main(final String[] args)
{
HistoryVariable hv = new HistoryVariable("a");
hv.update(90);
hv.update(12.1D);
System.out.println(hv.toString());
System.out.println(hv.undo());
System.out.println(hv.undo());
System.out.println(hv.undo());
System.out.println(hv.undo());
System.out.println(hv.toString());
hv.dispose();
System.out.println(hv.toString());
}
}

View file

@ -0,0 +1,15 @@
HV := new HistoryVariable
HV.var := 1
HV.var := 2
HV.var := "Latest value"
Msgbox % HV.var "`n" HV[2] "`n" HV[3]
class HistoryVariable {
__Set(aName, aValue) {
this.Insert(1,aValue)
Return aValue
}
__Get(aName) {
Return this[1]
}
}

View file

@ -0,0 +1,69 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace History
{
class Program
{
static void Main(string[] args)
{
var h = new HistoryObject();
h.Value = 5;
h.Value = "foo";
h.Value += "bar";
var history = h.ToArray();
for (int i = 0; i < history.Length; i++)
{
Console.Write("{0}{1}", history[i], ((i >= history.Length - 1) ? "\n" : " <- "));
}
h.Undo();
h.Undo();
h.Undo();
Console.WriteLine(h.Value);
}
private class HistoryObject : IEnumerable<object>
{
public HistoryObject()
{
_history = new Stack<object>(); // Initiates the history stack.
}
public object Value
{
get // Returns the top value from the history if there is one. Otherwise null.
{
if (_history.Count > 0)
return _history.Peek();
return null;
}
set { _history.Push(value); } // Adds the specified value to the history.
}
public void Undo()
{
if (_history.Count > 0)
_history.Pop(); // Removes the current value from the history.
}
// History stack that will hold all previous values of the object.
private readonly Stack<object> _history;
public IEnumerator<object> GetEnumerator()
{
return _history.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
}

View file

@ -0,0 +1,3 @@
(def a (ref 0))
(def a-history (atom [@a])) ; define a history vector to act as a stack for changes on variable a
(add-watch a :hist (fn [key ref old new] (swap! a-history conj new)))

View file

@ -0,0 +1,23 @@
(defmacro make-hvar (value)
`(list ,value))
(defmacro get-hvar (hvar)
`(car ,hvar))
(defmacro set-hvar (hvar value)
`(push ,value ,hvar))
;; Make sure that setf macro can be used
(defsetf get-hvar set-hvar)
(defmacro undo-hvar (hvar)
`(pop ,hvar))
(let ((v (make-hvar 1)))
(format t "Initial value = ~a~%" (get-hvar v))
(set-hvar v 2)
(setf (get-hvar v) 3) ;; Alternative using setf
(format t "Current value = ~a~%" (get-hvar v))
(undo-hvar v)
(undo-hvar v)
(format t "Restored value = ~a~%" (get-hvar v)))

View file

@ -0,0 +1,63 @@
import std.stdio, std.array, std.string, std.datetime, std.traits;
/// A history variable.
struct HistoryVariable(T) {
/// A value in a point in time.
static struct HistoryValue {
SysTime time;
T value;
// Alternative to the more common toString.
//void toString(scope void delegate(string) output) const {
void toString(scope void delegate(const(char)[]) output)const {
output(format("%s; %s", time, value));
}
}
const(HistoryValue)[] values;
private void addValue(T value) {
values ~= HistoryValue(Clock.currTime(), value);
}
void opAssign(T value) {
addValue(value);
}
@property T currentValue() const pure nothrow {
return values.back.value;
}
alias currentValue this;
@property auto history() const pure nothrow {
return values;
}
/**
Demonstrating D's compile-time reflection features. The member
functions that are in this 'static if' block would be added for
types T that are arrays (including strings). */
static if (isArray!T) {
// Append-with-assign operator.
void opOpAssign(string op : "~")(T element) {
addValue(currentValue ~ element);
}
// Similar implementation for other array operators...
}
}
void main() {
HistoryVariable!int x;
x = 1;
x = 2;
x = 3;
writefln("%(%s\n%)\n", x.history);
HistoryVariable!string s;
s = "hello";
s ~= " world";
s = "goodby";
writefln("%(%s\n%)", s.history);
}

View file

@ -0,0 +1,112 @@
program History_variables;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
type
THistoryVarType = record
value: variant;
timestamp: TDateTime;
function ToString: string;
end;
THistoryVar = record
Fvalue: variant;
FHistory: TArray<THistoryVarType>;
private
procedure SetValue(const Value: Variant);
function GetTimestamp: TDateTime;
public
property History: TArray<THistoryVarType> read FHistory;
constructor Init(val: variant);
function Dump: string;
function Recall(steps: Integer): variant; overload;
function Recall(timestamp: TDateTime): variant; overload;
property Timestamp: TDateTime read GetTimestamp;
property Value: Variant read Fvalue write SetValue;
end;
{ THistoryVar }
function THistoryVar.Dump: string;
begin
Result := '';
for var h in FHistory do
Result := Result + h.ToString + #10;
end;
function THistoryVar.GetTimestamp: TDateTime;
begin
if Length(FHistory) = 0 then
exit(0);
Result := FHistory[high(FHistory)].timestamp;
end;
constructor THistoryVar.Init(val: variant);
begin
SetLength(Fhistory, 0);
SetValue(val);
end;
function THistoryVar.Recall(timestamp: TDateTime): variant;
begin
for var h in FHistory do
begin
if h.timestamp = timestamp then
exit(h.value);
end;
result := Fvalue;
end;
function THistoryVar.Recall(steps: Integer): variant;
begin
if (steps <= 1) or (steps >= Length(FHistory)) then
exit(value);
result := FHistory[Length(FHistory) - steps - 1].value;
end;
procedure THistoryVar.SetValue(const Value: Variant);
begin
SetLength(FHistory, Length(FHistory) + 1);
FHistory[High(FHistory)].Value := Value;
FHistory[High(FHistory)].timestamp := now;
Fvalue := Value;
end;
{ THistoryVarType }
function THistoryVarType.ToString: string;
var
dt: string;
begin
DateTimeToString(dt, 'mm/dd/yyyy hh:nn:ss.zzz', timestamp);
Result := format('%s - %s', [dt, Value]);
end;
begin
var v := THistoryVar.Init(0);
v.Value := True;
Sleep(200);
if v.Value then
v.Value := 'OK';
Sleep(100);
if v.Value = 'OK' then
v.Value := PI;
writeln('History of variable values:'#10);
Writeln(v.Dump);
Writeln('Recall 2 steps');
Writeln(v.Recall(2));
var t := v.History[3].timestamp;
Writeln(#10'Recall to timestamp ', datetimetostr(t));
Writeln(v.Recall(t));
readln;
end.

View file

@ -0,0 +1,22 @@
(define-syntax-rule (make-h-var name) (define name (stack (gensym))))
(define-syntax-rule (h-get name) (stack-top name))
(define-syntax-rule (h-set name value) (push name value))
(define-syntax-rule (h-undo name)
(begin
(pop name)
(when ( stack-empty? name) (error "no more values" 'name))
(stack-top name)))
(define-syntax-rule (h-values name) (stack->list name))
;; usage
(make-h-var x)→ x
(h-set x 42) → 42
(h-set x 666)→ 666
(h-set x 'elvis)→ elvis
(h-values x) → (42 666 elvis) ;; historized values
(h-get x) → elvis
(h-undo x)→ 666
(h-undo x) → 42
(h-undo x) → ❌ error: no more values x

View file

@ -0,0 +1,57 @@
import extensions;
import system'collections;
import system'routines;
import extensions'routines;
class HistoryVariable
{
Stack previous := new Stack();
object value;
Value
{
get() = value;
set(value)
{
if ((this value) != nil)
{
previous.push(this value)
};
this value := value
}
}
undo()
{
ifnot (previous.isEmpty())
{
value := previous.pop()
}
else
{
value := nil
}
}
enumerator() => previous;
string toPrintable() => this value;
}
public program()
{
var o := new HistoryVariable();
o.Value := 5;
o.Value := "foo";
o.Value := o.Value + "bar";
console.printLine(o);
o.forEach:printingLn;
o.undo().undo().undo();
console.printLine(o.Value ?? "nil")
}

View file

@ -0,0 +1,12 @@
USING: accessors combinators formatting kernel models.history ;
1 <history> {
[ add-history ]
[ value>> "Initial value: %u\n" printf ]
[ 2 >>value add-history ]
[ 3 swap value<< ]
[ value>> "Current value: %u\n" printf ]
[ go-back ]
[ go-back ]
[ value>> "Restored value: %u\n" printf ]
} cleave

View file

@ -0,0 +1,5 @@
: history create here cell+ , 0 , -1 , ;
: h@ @ @ ;
: h! swap here >r , dup @ , r> swap ! ;
: .history @ begin dup cell+ @ -1 <> while dup ? cell+ @ repeat drop ;
: h-- dup @ cell+ @ dup -1 = if abort" End of history" then swap ! ;

View file

@ -0,0 +1,113 @@
package main
import (
"fmt"
"sort"
"sync"
"time"
)
// data type for history variable (its an int)
type history struct {
timestamp tsFunc
hs []hset
}
// data type for timestamp generator
type tsFunc func() time.Time
// data type for a "set" event
type hset struct {
int // new value
t time.Time // timestamp
}
// newHistory creates a history variable
func newHistory(ts tsFunc) history {
return history{ts, []hset{{t: ts()}}}
}
// int returns the current value
func (h history) int() int {
return h.hs[len(h.hs)-1].int
}
// set does what you expect and returns the timestamp recorded for the event
func (h *history) set(x int) time.Time {
t := h.timestamp()
h.hs = append(h.hs, hset{x, t})
return t
}
// dump displays a complete history
func (h history) dump() {
for _, hs := range h.hs {
fmt.Println(hs.t.Format(time.StampNano), hs.int)
}
}
// recall recalls the value stored in the history variable at time t.
// if the variable had not been created yet, ok is false.
func (h history) recall(t time.Time) (int, /*ok*/ bool) {
i := sort.Search(len(h.hs), func(i int) bool {
return h.hs[i].t.After(t)
})
if i > 0 {
return h.hs[i-1].int, true
}
return 0, false
}
// newTimestamper returns a function that generates unique timestamps.
// Use a single timestamper for multiple history variables to preserve
// an unambiguous sequence of assignments across the multiple history
// variables within a single goroutine.
func newTimestamper() tsFunc {
var last time.Time
return func() time.Time {
if t := time.Now(); t.After(last) {
last = t
} else {
last.Add(1)
}
return last
}
}
// newProtectedTimestamper generates unique timestamps for concurrent
// goroutines.
func newProtectedTimestamper() tsFunc {
var last time.Time
var m sync.Mutex
return func() (t time.Time) {
t = time.Now()
m.Lock() // m protects last
if t.After(last) {
last = t
} else {
last.Add(1)
t = last
}
m.Unlock()
return
}
}
func main() {
// enable history variable support appropriate for single goroutine.
ts := newTimestamper()
// define a history variable
h := newHistory(ts)
// assign three values. (timestamps kept for future reference.)
ref := []time.Time{h.set(3), h.set(1), h.set(4)}
// non-destructively display history
fmt.Println("History of variable h:")
h.dump()
// recall the three values. (this is non-destructive as well, but
// different than the dump in that values are recalled by time.)
fmt.Println("Recalling values:")
for _, t := range ref {
rv, _ := h.recall(t)
fmt.Println(rv)
}
}

View file

@ -0,0 +1,32 @@
import Data.IORef
newtype HVar a = HVar (IORef [a])
newHVar :: a -> IO (HVar a)
newHVar value = fmap HVar (newIORef [value])
readHVar :: HVar a -> IO a
readHVar (HVar ref) = fmap head (readIORef ref)
writeHVar :: a -> HVar a -> IO ()
writeHVar value (HVar ref) = modifyIORef ref (value:)
undoHVar :: HVar a -> IO ()
undoHVar (HVar ref) = do
(_ : history) <- readIORef ref
writeIORef ref history
getHistory :: HVar a -> IO [a]
getHistory (HVar ref) = readIORef ref
-- Testing
main :: IO ()
main = do
var <- newHVar 0
writeHVar 1 var
writeHVar 2 var
writeHVar 3 var
getHistory var >>= print
undoHVar var
undoHVar var
undoHVar var

View file

@ -0,0 +1,12 @@
varref_hist_=:'VAR','_hist_',~]
set_hist_=:4 :0
V=.varref x
if.0>nc<V do.(<V)=:''end.
(<V)=.V~,<y
y
)
getall_hist_=:3 :0
(varref y)~
)
length_hist_=: #@getall
get_hist_=: _1 {:: getall

View file

@ -0,0 +1,14 @@
'x' set_hist_ 9
9
'x' set_hist_ 10
10
'x' set_hist_ 11
11
get_hist_ 'x'
11
length_hist_ 'x'
3
getall_hist_ 'x'
┌─┬──┬──┐
│9│10│11│
└─┴──┴──┘

View file

@ -0,0 +1,73 @@
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* A class for an "Integer with a history".
* <p>
* Note that it is not possible to create an empty Variable (so there is no "null") with this type. This is a design
* choice, because if "empty" variables were allowed, reading of empty variables must return a value. Null is a
* bad idea, and Java 8's Optional<T> (which is somewhat like the the official fix for the null-bad-idea) would
* make things more complicated than an example should be.
*/
public class IntegerWithHistory {
/**
* The "storage Backend" is a list of all values that have been ever assigned to this variable. The List is
* populated front to back, so a new value is inserted at the start (position 0), and older values move toward the end.
*/
private final List<Integer> history;
/**
* Creates this variable and assigns the initial value
*
* @param value initial value
*/
public IntegerWithHistory(Integer value) {
history = new LinkedList<>();
history.add(value);
}
/**
* Sets a new value, pushing the older ones back in the history
*
* @param value the new value to be assigned
*/
public void set(Integer value) {
//History is populated from the front to the back, so the freshest value is stored a position 0
history.add(0, value);
}
/**
* Gets the current value. Since history is populuated front to back, the current value is the first element
* of the history.
*
* @return the current value
*/
public Integer get() {
return history.get(0);
}
/**
* Gets the entire history all values that have been assigned to this variable.
*
* @return a List of all values, including the current one, ordered new to old
*/
public List<Integer> getHistory() {
return Collections.unmodifiableList(this.history);
}
/**
* Rolls back the history one step, so the current value is removed from the history and replaced by it's predecessor.
* This is a destructive operation! It is not possible to rollback() beyond the initial value!
*
* @return the value that had been the current value until history was rolled back.
*/
public Integer rollback() {
if (history.size() > 1) {
return history.remove(0);
} else {
return history.get(0);
}
}
}

View file

@ -0,0 +1,25 @@
public class TestIntegerWithHistory {
public static void main(String[] args) {
//creating and setting three different values
IntegerWithHistory i = new IntegerWithHistory(3);
i.set(42);
i.set(7);
//looking at current value and history
System.out.println("The current value of i is :" + i.get());
System.out.println("The history of i is :" + i.getHistory());
//demonstrating rollback
System.out.println("Rolling back:");
System.out.println("returns what was the current value: " + i.rollback());
System.out.println("after rollback: " + i.get());
System.out.println("returns what was the current value: " + i.rollback());
System.out.println("after rollback: " + i.get());
System.out.println("Rolling back only works to the original value: " + i.rollback());
System.out.println("Rolling back only works to the original value: " + i.rollback());
System.out.println("So there is no way to 'null' the variable: " + i.get());
}
}

View file

@ -0,0 +1,76 @@
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* A Generic class for an "Anything with a history".
* <p>
* Note that it is not possible to create an empty Variable (so there is no "null") with this type. This is a design
* choice, because if "empty" variables were allowed, reading of empty variables must return a value. Null is a
* bad idea, and Java 8's Optional<T> (which is somewhat like the the official fix for the null-bad-idea) would
* make things more complicated than an example should be.
* <p>
* Also note that this "really works" only with constant Ts. If somebody keeps a reference to an assigned value,
* and is able to modify the state of this value through the reference , this will not be reflected in the history!
*/
public class WithHistory<T> {
/**
* The "storage Backend" is a list of all values that have been ever assigned to this variable. The List is
* populated front to back, so a new value is inserted at the start (position 0), and older values move toward the end.
*/
private final List<T> history;
/**
* Creates this variable and assigns the initial value
*
* @param value initial value
*/
public WithHistory(T value) {
history = new LinkedList<>();
history.add(value);
}
/**
* Sets a new value, pushing the older ones back in the history
*
* @param value the new value to be assigned
*/
public void set(T value) {
//History is populated from the front to the back, so the freshest value is stored a position 0
history.add(0, value);
}
/**
* Gets the current value. Since history is populuated front to back, the current value is the first element
* of the history.
*
* @return the current value
*/
public T get() {
return history.get(0);
}
/**
* Gets the entire history all values that have been assigned to this variable.
*
* @return a List of all values, including the current one, ordered new to old
*/
public List<T> getHistory() {
return Collections.unmodifiableList(this.history);
}
/**
* Rolls back the history one step, so the current value is removed from the history and replaced by it's predecessor.
* This is a destructive operation! It is not possible to rollback() beyond the initial value!
*
* @return the value that had been the cueent value until history was rolled back.
*/
public T rollback() {
if (history.size() > 1) {
return history.remove(0);
} else {
return history.get(0);
}
}
}

View file

@ -0,0 +1,15 @@
mutable struct Historied
num::Number
history::Vector{Number}
Historied(n) = new(n, Vector{Number}())
end
assign(y::Historied, z) = (push!(y.history, y.num); y.num = z; y)
x = Historied(1)
assign(x, 3)
assign(x, 5)
assign(x, 4)
println("Past history of variable x: $(x.history). Current value is $(x.num)")

View file

@ -0,0 +1,28 @@
// version 1.1.4
class HistoryVariable<T>(initialValue: T) {
private val history = mutableListOf<T>()
var currentValue: T
get() = history[history.size - 1]
set(value) {
history.add(value)
}
init {
currentValue = initialValue
}
fun showHistory() {
println("The variable's history, oldest values first, is:")
for (item in history) println(item)
}
}
fun main(args: Array<String>) {
val v = HistoryVariable(1)
v.currentValue = 2
v.currentValue = 3
v.showHistory()
println("\nCurrentvalue is ${v.currentValue}")
}

View file

@ -0,0 +1,30 @@
-- History variables in Lua 6/12/2020 db
local HistoryVariable = {
new = function(self)
return setmetatable({history={}},self)
end,
get = function(self)
return self.history[#self.history]
end,
set = function(self, value)
self.history[#self.history+1] = value
end,
undo = function(self)
self.history[#self.history] = nil
end,
}
HistoryVariable.__index = HistoryVariable
local hv = HistoryVariable:new()
print("defined:", hv)
print("value is:", hv:get())
--
hv:set(1); print("set() to:", hv:get())
hv:set(2); print("set() to:", hv:get())
hv:set(3); print("set() to:", hv:get())
--
print("history:", table.concat(hv.history,","))
--
hv:undo(); print("undo() to:", hv:get())
hv:undo(); print("undo() to:", hv:get())
hv:undo(); print("undo() to:", hv:get())

View file

@ -0,0 +1,34 @@
-- History variables in Lua 6/12/2020 db
local function HistoryVariable()
local history = {}
return {
get = function()
return history[#history]
end,
set = function(value)
history[#history+1] = value
end,
undo = function()
history[#history] = nil
end,
getHistory = function()
local clone = {}
for k,v in pairs(history) do clone[k]=v end
return clone
end
}
end
local hv = HistoryVariable()
print("defined:", hv)
print("value is:", hv.get())
--
hv.set(1); print("set() to:", hv.get())
hv.set(2); print("set() to:", hv.get())
hv.set(3); print("set() to:", hv.get())
--
print("history:", table.concat(hv.getHistory(),","))
--
hv.undo(); print("undo() to:", hv.get())
hv.undo(); print("undo() to:", hv.get())
hv.undo(); print("undo() to:", hv.get())

View file

@ -0,0 +1,38 @@
Flush ' empty curtrent stack
\\ a is a pointer to a new stack object
a=stack:=1,2@,3%
Print Len(A)=3
For i=1 to Len(a) {
Print StackType$(a, i)="Number"
}
b=stack
Print len(b)=0
Push 1, 2 \\ to current stack
Stack b {
\\ make b the current stack
Data 1, 2, 3
} ' Data add to bottom
\\ now current stack get the old object
Stack b {Push 1, 2, 3 } ' Push add to top, so 3 is at top
Stack b {
While not empty {
Read k ' Read used to pop value to a variable
\\ number pop value in an expression
Print k, number, ' 3 2 1 1 2 3
}
Print
}
z=[] ' [] pop all values from current stack to a new stack, and return a pointer
Print z ' 2 1
z=Stack(a, z,a, z) ' merge stack objects, to a new one, preserve a and z
Print Len(z)
\\ empty a using a new object
a=stack
b=stack:=1,2,3
\\ z has two stack objects
z=stack:= a, b
Stack b { data 1000}
b=stack ' b point to a new stack
\\ we get pointer back
b=stackitem(z, 2)
Print stackitem(b, 4)=1000

View file

@ -0,0 +1,179 @@
Module CheckHistoryVariables {
Class History {
Private:
myvalue=stack
Public:
Group Count {
Value {
link parent myvalue to m
=Len(m)
}
}
Function CopyMe {
m=This
.myvalue<=stack(.myvalue)
=Group(m)
}
Group CopyValues {
Value {
link parent myvalue to m
=Stack(m)
}
}
Function Values (x as long) {
if x>=0 and x<=len(.myvalue) then =StackItem(.myvalue, x)
Else Error "Fault index"
}
Module Back {
if len(.myvalue)<2 then exit
Stack .myvalue {Drop}
}
Operator "++" {
Stack .myvalue {
Push stackitem()+1
}
}
Operator "--" {
Stack .myvalue {
Push stackitem()-1
}
}
Operator "+=" (x) {
Stack .myvalue {
Push stackitem()+x
} }
Operator "-=" (x) {
Stack .myvalue {
Push stackitem()-x
}
}
Operator "/=" (x){
if x==0 then error "division by zero"
Stack .myvalue {
Push stackitem()/x
}
}
Operator "*=" (x){
Stack .myvalue {
Push stackitem()*x
}
}
Value {
=StackItem(.myvalue)
}
Set {
Read x : Stack .myvalue { Push x}
}
Class:
Module History {
If Match("N") then Read x : Stack .myvalue { Push x}
}
}
N=History()
N=1
N=2
N=3
Print N, N.Values(2), N.Values(3), N.Count
\\ Get a copy of history
m=N.CopyValues
Print len(m)=3
\\ just show all
Print m ' 3 2 1
\\ or iterate from last to first
k=each(m, -1, 1)
While k {
Print Stackitem(k) \\ 1 NL 2 NL 3 (NL = new line)
}
N1=N.CopyMe()
N=5
N1=4
N=6
Print N
Print N1.Count=4, N.Count=5
Print N1, N
Print N.CopyValues ' 6 5 3 2 1
Print N1.CopyValues ' 4 3 2 1
Print N1<N
N=N+1
Print N.Count=6
Print N.CopyValues ' 6 5 3 2 1
Print "Go Back"
While N.Count>1 {
N.Back
Print N
}
N+=10
N*=2
Print N.CopyValues ' 22 11 1
}
CheckHistoryVariables
\\ for strings
Module CheckStringHistoryVariables {
Class History$ {
Private:
myvalue=stack
Public:
Group Count {
Value {
link parent myvalue to m
=Len(m)
}
}
Function CopyMe {
m=This
.myvalue<=stack(.myvalue)
=Group(m)
}
Group CopyValues {
Value {
link parent myvalue to m
=Stack(m)
}
}
Function Values$ (x as long) {
if x>=0 and x<=len(.myvalue) then =StackItem$(.myvalue, x)
Else Error "Fault index"
}
Module Back {
if len(.myvalue)<2 then exit
Stack .myvalue {Drop}
}
Operator "+=" (x$) {
Stack .myvalue {
Push stackitem$()+x$
} }
Value {
=StackItem$(.myvalue)
}
Set {
Read x$ : Stack .myvalue { Push x$}
}
Class:
Module History {
If Match("S") then Read x$ : Stack .myvalue { Push x$}
}
}
N$=History$("First")
N$="Second"
N$="Third"
Print N.Count=3
M=N.CopyValues
K=Each(M, -1, 1)
While K {
Print StackItem$(K)
}
N$+=" and this"
Print N.Count=4
Print N.CopyValues
N.Back
Print N.Count=3
Print N.CopyValues
Print N.Values$(2)="Second"
Input "New value:", N$
Print N$
Print N.Count=4
Print N.CopyValues
}
CheckStringHistoryVariables

View file

@ -0,0 +1,46 @@
type HistoryVar[T] = object
hist: seq[T]
func initHistoryVar[T](value: T = T.default): HistoryVar[T] =
## Initialize a history variable with given value.
result.hist.add value
func set(h: var HistoryVar; value: h.T) =
## Set the history variable to given value.
h.hist.add value
func get(h: HistoryVar): h.T =
## Return the current value of history variable.
h.hist[^1]
proc showHistory(h: HistoryVar) =
## Show the history starting from oldest values.
for i, value in h.hist:
echo i, ": ", value
func pop(h: var HistoryVar): h.T =
## Pop the current value and return it.
if h.hist.len > 1: h.hist.pop() else: h.hist[0]
when isMainModule:
var h = initHistoryVar[int]() # Initialized to 0.
echo "Assigning three values: 1, 2, 3"
h.set(1) # 0, 1
h.set(2) # 0, 1, 2
h.set(3) # 0, 1, 2, 3
echo "History (oldest values first):"
h.showHistory()
echo "Current value is ", h.get()
echo "Recall the three values:"
echo h.pop() # -> 3, last value removed.
echo h.pop() # -> 2, last value removed.
echo h.pop() # -> 1, last value removed.
echo "History (note that initial value can never be removed):"
h.showHistory()

View file

@ -0,0 +1,16 @@
open Stack
(* The following line is only for convenience when typing code *)
module H = Stack
let show_entry e =
Printf.printf "History entry: %5d\n" e
let () =
let hs = H.create() in
H.push 111 hs ;
H.push 4 hs ;
H.push 42 hs ;
H.iter show_entry hs;
hs |> H.pop |> Printf.printf "%d\n";
hs |> H.pop |> Printf.printf "%d\n";
hs |> H.pop |> Printf.printf "%d\n"

View file

@ -0,0 +1,179 @@
MODULE HVar;
IMPORT Out, Conv;
TYPE
(* Generic Object *)
Object* = POINTER TO ObjectDesc;
ObjectDesc = RECORD
Show: PROCEDURE(o:Object);
AsString: PROCEDURE(o: Object; VAR str: ARRAY OF CHAR);
END;
(* Integers *)
Integer = POINTER TO IntegerDesc;
IntegerDesc = RECORD (ObjectDesc)
val: INTEGER;
END;
(* Chars *)
Char = POINTER TO CharDesc;
CharDesc = RECORD (ObjectDesc)
val: CHAR;
END;
Node = POINTER TO NodeDesc;
NodeDesc = RECORD
val: Object;
next: Node;
END;
(* History Variable *)
HVar* = POINTER TO HVarDesc;
HVarDesc = RECORD
first, last: Node;
size-: INTEGER;
END;
PROCEDURE CharAsString(o:Object; VAR dst: ARRAY OF CHAR);
BEGIN
IF LEN(dst) >= 2 THEN
dst[1] := 0X;
END;
dst[0] := o(Char)^.val
END CharAsString;
PROCEDURE IntAsString(o:Object; VAR dst: ARRAY OF CHAR);
BEGIN
Conv.ConvInt(o(Integer)^.val,dst);
END IntAsString;
PROCEDURE ShowInt(o:Object);
BEGIN
Out.Int(o(Integer)^.val,10);
END ShowInt;
PROCEDURE ShowChar(o:Object);
BEGIN
Out.Char(o(Char)^.val);
END ShowChar;
PROCEDURE BoxChar(val: CHAR): Char;
VAR
c: Char;
BEGIN
NEW(c);
c^.val := val;
c^.Show := ShowChar;
c^.AsString := CharAsString;
RETURN c;
END BoxChar;
PROCEDURE BoxInt(val:INTEGER): Integer;
VAR
i: Integer;
BEGIN
NEW(i);
i^.val := val;
i^.Show := ShowInt;
i^.AsString := IntAsString;
RETURN i;
END BoxInt;
PROCEDURE InitNode(): Node;
VAR
l: Node;
BEGIN
NEW(l);
l.val := NIL;
l.next := NIL;
RETURN l;
END InitNode;
PROCEDURE InitHVar(): HVar;
VAR
hv: HVar;
BEGIN
NEW(hv);
hv.first := NIL;
hv.last := NIL;
hv.size := 0;
RETURN hv;
END InitHVar;
PROCEDURE (v: HVar) Value(): Object;
BEGIN
RETURN v^.first^.val;
END Value;
PROCEDURE (v: HVar) Set(o: Object);
VAR
l: Node;
BEGIN
l := InitNode();
l^.val := o;
IF (v^.first = v^.last) & (v^.first = NIL) THEN
v^.first := l;
v^.last := l;
INC(v^.size);
ELSIF (v^.first = v^.last) & (v^.first # NIL) THEN
v^.first^.next := l;
v^.last := v^.first.next;
INC(v^.size);
ELSIF (v^.first # v^.last) THEN
v^.last^.next := l;
v^.last := l;
INC(v^.size);
END
END Set;
PROCEDURE (v: HVar) Undo(): Object;
VAR
o: Object;
BEGIN
IF (v^.first = v^.last) & (v^.first = NIL) THEN
o := NIL;
ELSIF (v^.first = v^.last) & (v^.first # NIL) THEN
o := v^.first^.val;
v^.first := NIL;
v^.last := NIL;
DEC(v^.size);
ELSE
o := v^.first^.val;
v^.first := v^.first^.next;
DEC(v^.size);
END;
RETURN o;
END Undo;
PROCEDURE (v: HVar) Print();
VAR
iter : Node;
BEGIN
iter := v.first;
WHILE(iter # NIL) DO
iter^.val^.Show(iter^.val);
iter := iter^.next;
END;
Out.Ln;
END Print;
PROCEDURE ShowVal(val: Object);
VAR
s: ARRAY 128 OF CHAR;
BEGIN
val^.AsString(val,s);
Out.String("> ");Out.String(s);Out.Ln;
END ShowVal;
VAR
history: HVar;
BEGIN
history := InitHVar();
history.Set(BoxChar(64X));
history.Set(BoxInt(10));
history.Set(BoxInt(15));
history.Set(BoxInt(20));
history.Print();
ShowVal(history.Undo());
ShowVal(history.Undo());
ShowVal(history.Undo());
END HVar.

View file

@ -0,0 +1,58 @@
'============
class History
'============
indexbase 0
string buf
sys ii,ld,pb
method constructor(sys n=1000, l=sizeof sys) {buf=nuls n*l : pb=strptr buf : ld=l : ii=0}
method destructor () {clear}
'
method setup(sys n=1000, l=sizeof sys) {buf=nuls n*l : pb=strptr buf : ld=l : ii=0}
method clear() {buf="" : pb=0 : ld=0 : ii=0}
method max (sys i) {if i>ii{ii=i}}
method count() as sys {return ii}
method size () as sys {return ld}
'
method get (any*p,i) {copy @p, pb+i*ld,ld } 'out
method add (any*p) {copy pb+ii*ld,@p,ld : ii++} 'in
method put (any*p,sys i) {copy pb+i*ld,@p,ld : max i} 'in
'
end class
'====
'TEST
'====
'this works for fixed length types
'it will not work for types containing
'volatile pointers. eg: string members
type vector double x,y,z
vector v
new History hv(1000,sizeof v) 'give number of records and variable size
sys i
for i=0 to 9
v<=i,i*10,i*100 'assign new values to vector
hv.add v 'add to history
next
string tab=chr(9) : cr=chr(13)+chr(10)
string pr="Data History of v" cr cr
pr+="n" tab "x" tab "y" tab "z" cr
vector sv
'
for i=hv.count()-1 to 0 step -1
hv.get sv,i
pr+=i tab sv.x tab sv.y tab sv.z cr
next
print pr 'result '9,90,900 : 8,80,800 ...
del hv

View file

@ -0,0 +1,10 @@
default(histsize, 1000) \\ or some other positive number to suit
1+7
sin(Pi)
2^100
\a1 \\ display history item #1, etc.
% \\ alternate syntax
%1 \\ alternate syntax
\a2
\a3
[%1, %2, %3] \\ or any other command using these values

View file

@ -0,0 +1,9 @@
declare t float controlled;
do i = 1 to 5; /* a loop to read in and save five values. */
allocate t; get (t);
end;
do while (allocation(t) > 0); /* a loop to retrieve the values. */
put (t); free t;
end;

View file

@ -0,0 +1,11 @@
Turn history on <@ DEFHST>__on</@>
Notify Protium we are interested in the variable mv
<@ DEFHST>mv</@>
Assign a value: <@ LETVARLIT>mv|first value</@><@ SAYVAR>mv</@>
Reassign the value: <@ LETVARLIT>mv|second value</@><@ SAYVAR>mv</@>
Reassign the value: <@ LETVARLIT>mv|third value</@><@ SAYVAR>mv</@>
Dump history <@ SAYDMPHSTVAR>mv</@>
Current value: <@ SAYVAR>mv</@>
Undo once: <@ ACTUNDVAR>mv</@><@ SAYVAR>mv</@>
Undo twice: <@ ACTUNDVAR>mv</@><@ SAYVAR>mv</@>
Turn history off <@ DEFHST>__off</@>

View file

@ -0,0 +1,11 @@
Turn history on <# 定义变量史>__on</#>
Notify Protium we are interested in the variable mv
<# 定义变量史>mv</#>
Assign a value: <# 指定变量字串>mv|first value</#><# 显示变量>mv</#>
Reassign the value: <# 指定变量字串>mv|second value</#><# 显示变量>mv</#>
Reassign the value: <# 指定变量字串>mv|third value</#><# 显示变量>mv</#>
Dump history <# 显示全内容变量史变量>mv</#>
Current value: <# 显示变量>mv</#>
Undo once: <# 运行撤消变量>mv</#><# 显示变量>mv</#>
Undo twice: <# 运行撤消变量>mv</#><# 显示变量>mv</#>
Turn history off <# 定义变量史>__off</#>

View file

@ -0,0 +1,40 @@
package History;
sub TIESCALAR {
my $cls = shift;
my $cur_val = shift;
return bless [];
}
sub FETCH {
return shift->[-1]
}
sub STORE {
my ($var, $val) = @_;
push @$var, $val;
return $val;
}
sub get(\$) { @{tied ${+shift}} }
sub on(\$) { tie ${+shift}, __PACKAGE__ }
sub off(\$) { untie ${+shift} }
sub undo(\$) { pop @{tied ${+shift}} }
package main;
my $x = 0;
History::on($x);
for ("a" .. "d") { $x = $_ }
print "History: @{[History::get($x)]}\n";
for (1 .. 3) {
print "undo $_, ";
History::undo($x);
print "current value: $x\n";
}
History::off($x);
print "\$x is: $x\n";

View file

@ -0,0 +1,5 @@
History: a b c d
undo 1, current value: c
undo 2, current value: b
undo 3, current value: a
$x is: a

View file

@ -0,0 +1,15 @@
-->
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (desktop/Phix only)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">history</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">type</span> <span style="color: #000000;">hvt</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">o</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">history</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">history</span><span style="color: #0000FF;">,</span><span style="color: #000000;">o</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">type</span>
<span style="color: #000000;">hvt</span> <span style="color: #000000;">test</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">test</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span>
<span style="color: #000000;">test</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">3</span>
<span style="color: #0000FF;">?{</span><span style="color: #008000;">"current"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">test</span><span style="color: #0000FF;">}</span>
<span style="color: #0000FF;">?{</span><span style="color: #008000;">"history"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">history</span><span style="color: #0000FF;">}</span>
<!--

View file

@ -0,0 +1,21 @@
(phixonline)-->
<span style="color: #000080;font-style:italic;">-- history.e</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">histories</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">global</span> <span style="color: #008080;">function</span> <span style="color: #000000;">new_history_id</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">histories</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">histories</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">v</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">histories</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">global</span> <span style="color: #008080;">procedure</span> <span style="color: #000000;">set_hv</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">hv</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">object</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">histories</span><span style="color: #0000FF;">[</span><span style="color: #000000;">hv</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">histories</span><span style="color: #0000FF;">[</span><span style="color: #000000;">hv</span><span style="color: #0000FF;">],</span><span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">global</span> <span style="color: #008080;">function</span> <span style="color: #000000;">get_hv</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">hv</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">histories</span><span style="color: #0000FF;">[</span><span style="color: #000000;">hv</span><span style="color: #0000FF;">][$]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">global</span> <span style="color: #008080;">function</span> <span style="color: #000000;">get_hv_full_history</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">hv</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">histories</span><span style="color: #0000FF;">[</span><span style="color: #000000;">hv</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<!--

View file

@ -0,0 +1,9 @@
(phixonline)-->
<span style="color: #008080;">include</span> <span style="color: #000000;">history</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">test2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">new_history_id</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">set_hv</span><span style="color: #0000FF;">(</span><span style="color: #000000;">test2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">set_hv</span><span style="color: #0000FF;">(</span><span style="color: #000000;">test2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?{</span><span style="color: #008000;">"current"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">get_hv</span><span style="color: #0000FF;">(</span><span style="color: #000000;">test2</span><span style="color: #0000FF;">)}</span>
<span style="color: #0000FF;">?{</span><span style="color: #008000;">"history"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">get_hv_full_history</span><span style="color: #0000FF;">(</span><span style="color: #000000;">test2</span><span style="color: #0000FF;">)}</span>
<!--

View file

@ -0,0 +1,8 @@
(de setH ("Var" Val)
(when (val "Var")
(with "Var"
(=: history (cons @ (: history))) ) )
(set "Var" Val) )
(de restoreH ("Var")
(set "Var" (pop (prop "Var" 'history))) )

View file

@ -0,0 +1,49 @@
; integer history variable
Structure historyint
List value.i()
EndStructure
Procedure SetInt (*var.historyint, val.i)
AddElement(*var\value())
If (ListSize(*var\value()) = 1)
*var\value() = 0
AddElement(*var\value())
EndIf
*var\value() = val
EndProcedure
Procedure ShowHistory (*var.historyint)
ForEach *var\value()
Debug *var\value()
Next
EndProcedure
Procedure UndoInt (*var.historyint)
If (ListSize(*var\value()) = 1)
ProcedureReturn
EndIf
DeleteElement(*var\value())
EndProcedure
;----------------------------------------------
Define x.historyint
For i = 0 To 3
setint(x, Random(50)+100 )
Next
Debug "x history:"
ShowHistory(x)
Debug ""
For i = 0 To 3
UndoInt(x)
Debug "undo, x = "+Str(x\value())
Next

View file

@ -0,0 +1,34 @@
import sys
HIST = {}
def trace(frame, event, arg):
for name,val in frame.f_locals.items():
if name not in HIST:
HIST[name] = []
else:
if HIST[name][-1] is val:
continue
HIST[name].append(val)
return trace
def undo(name):
HIST[name].pop(-1)
return HIST[name][-1]
def main():
a = 10
a = 20
for i in range(5):
c = i
print "c:", c, "-> undo x3 ->",
c = undo('c')
c = undo('c')
c = undo('c')
print c
print 'HIST:', HIST
sys.settrace(trace)
main()

View file

@ -0,0 +1,2 @@
c: 4 -> undo x3 -> 1
HIST: {'a': [10, 20], 'i': [0, 1, 2, 3, 4], 'c': [0, 1], 'name': ['c']}

View file

@ -0,0 +1,22 @@
/*REXX program demonstrates a method to track history of assignments to a REXX variable.*/
varSet!.=0 /*initialize the all of the VARSET!'s. */
call varSet 'fluid',min(0,-5/2,-1) ; say 'fluid=' fluid
call varSet 'fluid',3.14159 ; say 'fluid=' fluid
call varSet 'fluid',' Santa Claus' ; say 'fluid=' fluid
call varSet 'fluid',,999
say 'There were' result "assignments (sets) for the FLUID variable."
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
varSet: arg ?x; parse arg ?z, ?v, ?L /*obtain varName, value, optional─List.*/
if ?L=='' then do /*not la ist, so set the X variable.*/
?_=varSet!.0.?x+1 /*bump the history count (# of SETs). */
varSet!.0.?x=?_ /* ... and store it in the "database"*/
varSet!.?_.?x=?v /* ... and store the SET value. */
call value(?x),?v /*now, set the real X variable. */
return ?v /*also, return the value for function. */
end
say /*show a blank line for readability. */
do ?j=1 to ?L while ?j<=varSet!.0.?x /*display the list of "set" history. */
say 'history entry' ?j "for var" ?z":" varSet!.?J.?x
end /*?j*/
return ?j-1 /*return the number of assignments. */

View file

@ -0,0 +1,40 @@
/* REXX ***************************************************************
* Demonstrate how the history of assignments can be kept and shown
* 13.07.2012 Walter Pachl Rewrite of Version 1 for (my) readability
* varset.i.varu contains the ith value assigned to var
* varset.0.varu contains the number of assignments so far
**********************************************************************/
varset.=0 /*initialize the assignment count */
call varset 'fluid',min(0,-5/2,-1) ; say 'fluid=' fluid
call varset 'fluid',3.14159 ; say 'fluid=' fluid
call varset 'fluid',3.14159 ; say 'fluid=' fluid
call varset 'fluid',' Santa Claus' ; say 'fluid=' fluid
call varset 'FLUID',' Easter Rabbit' ; say 'fluid=' fluid
say 'There were' varset('fluid',,'L'),
'assignments (sets) for the FLUID variable.'
exit
varset: Procedure Expose varset.
/**********************************************************************
* record values assigned to var (=varu as Rexx is case insensitive)
* Invoke with list<>'' to list the sequence of assigned values
* and return the number of assignments made (using this routine)
**********************************************************************/
Parse Upper Arg varu /* name of variable in uppercase */
Parse arg var,value,list /*varName, value, optional-List. */
if list='' then do /*not list, so set the X variable*/
z=varset.0.varu+1 /*bump the history count (SETs). */
varset.z.varu=value /* ... and store it in "database"*/
varset.0.varu=z /*the new history count */
call value var,value /*now assign the value to var */
end
else Do
Say '' /*show blank line for readability*/
do i=1 to varset.0.varu /*list the assignment history */
say 'history entry' i "for var" var":" varset.i.varu
end
end
Return varset.0.varu /*return the number of assignments. */

View file

@ -0,0 +1,29 @@
#lang racket
(require rackunit)
(struct hvar (current history) #:mutable)
(define (make-hvar v) (hvar v empty))
(define (hvar-set! hv new)
(match-define (hvar cur hist) hv)
(set-hvar-history! hv (cons cur hist))
(set-hvar-current! hv new))
(define (hvar-undo! hv)
(match-define (hvar cur (cons old hist)) hv)
(set-hvar-current! hv old)
(set-hvar-history! hv hist))
;; unit tests
(define hv (make-hvar 0))
(hvar-set! hv 1)
(check-equal? (hvar-current hv) 1)
(hvar-set! hv 2)
(hvar-set! hv 3)
(check-equal? (hvar-history hv) '(2 1 0))
(hvar-undo! hv)
(hvar-undo! hv)
(hvar-undo! hv)
(check-equal? (hvar-current hv) 0)

View file

@ -0,0 +1,18 @@
class HistoryVar {
has @.history;
has $!var handles <Str gist FETCH Numeric>;
method STORE($val) is rw {
push @.history, [now, $!var];
$!var = $val;
}
}
my \foo = HistoryVar.new;
foo = 1;
foo = 2;
foo += 3;
foo = 42;
.say for foo.history;
say "Current value: {foo}";

View file

@ -0,0 +1,8 @@
foo_hist = []
trace_var(:$foo){|v| foo_hist.unshift(v)}
$foo = "apple"
$foo = "pear"
$foo = "banana"
p foo_hist # => ["banana", "pear", "apple"]

View file

@ -0,0 +1,43 @@
#[derive(Clone, Debug)]
struct HVar<T> {
history: Vec<T>,
current: T,
}
impl<T> HVar<T> {
fn new(val: T) -> Self {
HVar {
history: Vec::new(),
current: val,
}
}
fn get(&self) -> &T {
&self.current
}
fn set(&mut self, val: T) {
self.history.push(std::mem::replace(&mut self.current, val));
}
fn history(&self) -> (&[T], &T) {
(&self.history, &self.current)
}
fn revert(&mut self) -> Option<T> {
self.history
.pop()
.map(|val| std::mem::replace(&mut self.current, val))
}
}
fn main() {
let mut var = HVar::new(0);
var.set(1);
var.set(2);
println!("{:?}", var.history());
println!("{:?}", var.revert());
println!("{:?}", var.revert());
println!("{:?}", var.revert());
println!("{:?}", var.get());
}

View file

@ -0,0 +1,20 @@
class HVar[A](initialValue: A) extends Proxy {
override def self = !this
override def toString = "HVar(" + !this + ")"
def history = _history
private var _history = List(initialValue)
def unary_! = _history.head
def :=(newValue: A): Unit = {
_history = newValue :: _history
}
def modify(f: A => A): Unit = {
_history = f(!this) :: _history
}
def undo: A = {
val v = !this
_history = _history.tail
v
}
}

View file

@ -0,0 +1,21 @@
scala> val h = new HVar(3)
h: HVar[Int] = HVar(3)
scala> h := 11
scala> h := 90
scala> !h
res32: Int = 90
scala> h.history
res33: List[Int] = List(90, 11, 3)
scala> h.undo
res34: Int = 90
scala> h.undo
res35: Int = 11
scala> h.undo
res36: Int = 3

View file

@ -0,0 +1,14 @@
// HistoryVariable.script
properties
history: [], -- a list of all historical values
asTextFormat:"[[the last item of my history]]" -- always display the last value
end properties
to set newValue
push newValue nested into my history
end set
to rollback
pop my history
return it
end rollback

View file

@ -0,0 +1,20 @@
set x to be a new HistoryVariable
tell x to set "Hello"
put "x is now" && x -- display the current value
tell x to set 88
put "x is now" && x
tell x to set "World"
put "x is now" && x
put "History of x:" && x's history -- non-destructively display the history
tell x to set [9,6,3] -- set it to a list
put "x is now" && x
put "History of x:" && the history of x
put "Rolling back:" && x.rollback -- remove the last value
put "After rollback, x is now" && x

View file

@ -0,0 +1,28 @@
class HistoryVar(v) {
has history = []
has variable = v
method ≔(value) {
history << variable
variable = value
}
method to_s {
"#{variable}"
}
method AUTOLOAD(_, name, *args) {
variable.(name)(args...)
}
}
var foo = HistoryVar(0)
foo ≔ 1
foo ≔ 2
foo ≔ foo+3
foo ≔ 42
say "History: #{foo.history}"
say "Current value: #{foo}"

View file

@ -0,0 +1,35 @@
Object subclass:'HVar'
instanceVariableNames:'values'
classVariableNames:''
poolDictionaries:''
category:'example'.
!
!HVar methodsFor:'accessing'!
<-- value
(values ifNil:[values := OrderedCollection new]) add:value.
^ value
!
value
^ values last
!
undo
values removeLast.
!
history
^ history
! !
|x|
x := HVar new.
x <-- 1.
x value.
x <-- 2.
x <-- (x value + 1).
x value.
x history.

View file

@ -0,0 +1,11 @@
var historyOfHistory = [Int]()
var history:Int = 0 {
willSet {
historyOfHistory.append(history)
}
}
history = 2
history = 3
history = 4
println(historyOfHistory)

View file

@ -0,0 +1,38 @@
struct History <T> {
private var _history = [T]()
var history : [T] {
return _history
}
var now : T {
return history.last!
}
init(_ firstValue:T) {
_history = [firstValue]
}
mutating func set(newValue:T) {
_history.append(newValue)
}
mutating func undo() -> T {
guard _history.count > 1 else { return _history.first! }
_history.removeLast()
return _history.last!
}
}
var h = History("First")
h.set("Next")
h.set("Then")
h.set("Finally")
h.history // output ["First", "Next", "Then", "Finally"]
h.now // outputs "Finally"
h.undo() // outputs "Then"
h.undo() // outputs "Next"
h.undo() // outputs "First"
h.undo() // outputs "First", since it can't roll back any further
h.undo() // outputs "First"

View file

@ -0,0 +1,33 @@
# Define the history machinery
proc histvar {varName operation} {
upvar 1 $varName v ___history($varName) history
switch -- $operation {
start {
set history {}
if {[info exist v]} {
lappend history $v
}
trace add variable v write [list histvar.write $varName]
trace add variable v read [list histvar.read $varName]
}
list {
return $history
}
undo {
set history [lrange $history 0 end-1]
}
stop {
unset history
trace remove variable v write [list histvar.write $varName]
trace remove variable v read [list histvar.read $varName]
}
}
}
proc histvar.write {key varName args} {
upvar 1 $varName v ___history($key) history
lappend history $v
}
proc histvar.read {key varName args} {
upvar 1 $varName v ___history($key) history
set v [lindex $history end]
}

View file

@ -0,0 +1,13 @@
# Enable history for foo
histvar foo start
set foo {a b c d}
set foo 123
set foo "quick brown fox"
puts $foo
puts foo-history=[join [histvar foo list] ", "]
puts $foo
histvar foo undo
puts $foo
histvar foo undo
puts $foo
histvar foo stop

View file

@ -0,0 +1,19 @@
class HistoryVariable {
construct new(initValue) {
_history = [initValue]
}
currentValue { _history[-1] }
currentValue=(newValue) { _history.add(newValue) }
showHistory() {
System.print("The variable's history, oldest values first, is:")
for (item in _history) System.print(item)
}
}
var v = HistoryVariable.new(1)
v.currentValue = 2
v.currentValue = 3
v.showHistory()
System.print("\nCurrent value is %(v.currentValue)")

View file

@ -0,0 +1,18 @@
class HistoryVar{
var [private] _v, _history=List(), maxSz;
fcn init(v,maxEntries=3){ maxSz=maxEntries; set(v) }
fcn set(v){
_v=v; _history.append(T(Time.Clock.time,v));
if(_history.len()>maxSz) _history.del(0);
self
}
fcn get(n=0){ // look back into history
z:=_history.len();
n=(if(n>=z) 0 else z-n-1);
_history[n][1]
}
var [proxy] v=fcn{ _v };
var [proxy] history=
fcn{ _history.pump(List,fcn([(t,v)]){ T(Time.Date.ctime(t),v) }) };
fcn __opAdd(x){ set(_v + x); self }
}

View file

@ -0,0 +1,6 @@
hv:=HistoryVar(123);
hv+4;
hv.set("Shuttle prepared for liftoff");
hv+": orbit achived";
hv.history.concat("\n").println();
hv.get(3).println("<-- value two changes ago");