History variables: Difference between revisions

→‎{{header|Ada}}: Added Ada version
(→‎{{header|REXX}}: added the REXX language. -- ~~~~)
(→‎{{header|Ada}}: Added Ada version)
Line 19:
For extra points, if the language of choice does not support history variables, demonstrate how this might be implemented.
 
=={{header|C sharpAda}}==
 
Ada does not natively support history variables -- we have to implement them.
 
Furthermore, Ada is a strongly typed language -- that means, we would need to write a history variable type for every basic item type. Instead, we write a single generic package "History_Variables" that works for any item type. Here is the specification:
 
<lang Ada>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, ect.
-- 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), ect.
-- 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;</lang>
 
The implementation of "History_Variables":
 
<lang Ada>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;</lang>
 
And here is the real program, using a history variable of type Integer:
 
<lang Ada>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;</lang>
 
The program generates the following output:
 
<pre> 3 7 9
19</pre>
 
=={{header|C sharp}}==
<lang c sharp>using System;
using System.Collections;
Line 95 ⟶ 213:
<pre>foobar <- foo <- 5
</pre>
 
=={{header|Go}}==
We're all in this for the extra points. Mallon and Takota seem happy with sequences, but time and timestamps were mentioned on LtU. Beyond a separate sequence for each history variable, timestamps enable multiple variables to be seen in a common temporal sequence. In Go, with it's attention to concurrency, this might be done with flexibility for proper handling of shared variables, and efficient handling of variables limited to a single thread.
Anonymous user