人們常常看著照片回憶起從前,清晰地感覺到童年,青年,中年,老年一路走來的各種變化。從這種變化中,我們可以抽象出3個關(guān)鍵詞:對象、時間和狀態(tài)。對象擁有狀態(tài)和標(biāo)識,在標(biāo)識不變的情況下,狀態(tài)隨時間發(fā)展演變。這實際上代表了一種動態(tài)的世界觀:時間本身并不屬于世界,世界是在時間維度上不斷演變的狀態(tài)。在這種世界觀的指導(dǎo)下,通過計算機程序模擬現(xiàn)實世界問題時,我們用計算機中的對象狀態(tài)表示世界的狀態(tài),用計算機中對象的狀態(tài)的變化表示世界狀態(tài)的變化和時間進程。
與上面動態(tài)的世界觀不同,另一種世界觀認(rèn)為世界本質(zhì)上是靜止的。怎么理解呢?比如:對于一個歷史人物,在他生活的每一天里都有變化,從這個角度看是狀態(tài)的變化;但是如果縱觀他的一生,其人生軌跡作為一個整體又是靜止的,我們可以把這個整體作為一個研究的對象。這里,我們實際上把時間維度也納入對象屬性,使在3維中運動的對象變成了在4維中靜止的對象。物理學(xué)上稱對象在4維空間中的軌跡為對象的世界線(World Line)。另外,即使不是已經(jīng)蓋棺定論的對象,假如對象是有規(guī)律的,比如:一個物體的運動狀態(tài)由某一個公式完全決定,即未來某一時刻它處于什么位置也是完全確定的,那么我們只要掌握了這個公式就掌握了物體的世界線。
我們把對象的世界線用x(t)來表示,如果時間是離散的,我們可以用一個序列(Sequence)來表示x(t)。與計算的對象模型通過狀態(tài)改變來隱式地表示時間不同,我們可以把計算認(rèn)為是輸入序列input(t)到輸出序列output(t)的變換,時間是通過離散序列的方式顯式表示的。我們的程序?qū)嶋H上扮演了一個信號處理器的角色。
但有限序列的缺點在于它要求輸入是完整的,因而無法處理交互的情況,比如:我們把用戶的鍵盤輸入input(t)無法用一個有限序列來表示。為了處理交互,我們引入了可用惰性求值的流(Stream)。流可用視為可用惰性求值的無窮序列,這樣我們的程序就是一個信號處理器,輸入時一個流,輸出也是一個流。為了幫助理解,下面我們用一個C#實現(xiàn)的Stack的例子來說明:
//C#實現(xiàn)的基于流的Stack
public enum OperationType { PUSH, POP}
public struct Input{
public OperationType Operation;
public int Data;
}
class Stack
{
public static IEnumerable<int> Transform(IEnumerable<Input> aSourceStream)
{
LinkedList<int> list = new LinkedList<int>();
foreach(Input command in aSourceStream)
{
if(OperationType.PUSH== command.Operation)
{
list.AddLast(command.Data);
}
else if (OperationType.POP == command.Operation)
{
int data = list.Last.Value;
list.RemoveLast();
yield return data;
}
}
}
}
public class InputGenerator
{
public static IEnumerable<Input> Generate()
{
while (true)
{
string line = Console.ReadLine();
if (line.StartsWith("push "))
{
yield return new Input { Operation = OperationType.PUSH, Data = int.Parse(line.Split(' ')[1]) };
}
else if (line == "pop")
{
yield return new Input { Operation = OperationType.POP };
}
}
}
}
public static void Main(string[] args)
{
foreach (int output in Stack.Transform(InputGenerator.Generate()))
{
Console.WriteLine(output);
}
}
運行示例:
>>push 1
>>push 2
>>pop
2
>>push 3
>>pop
3
上面的例子中用戶的輸入被包裝成無窮的Input輸入流,Stack是從Input輸入流到int輸出流的信號處理器。