declare [QTk]={Module.link ['x-oz://system/wp/QTk.ozf']} proc {DrawGraph VSize L} C Tag Desc=td( canvas(handle:C width:500 height:VSize*2) lr(button(text:"Left" action:MoveLeft) button(text:"Right" action:MoveRight) button(text:"Up" action:MoveUp) button(text:"Down" action:MoveDown) )) CurrX = {NewCell 0} CurrY = {NewCell 0} proc{MoveLeft} CurrX := @CurrX - 5 {Tag delete} if @CurrX < 0 then CurrX := 0 end {DrawRec {List.drop L @CurrX} 0 @CurrX nil 10} end proc{MoveRight} CurrX := @CurrX + 5 {Tag delete} {DrawRec {List.drop L @CurrX} 0 @CurrX nil 10} end proc{MoveDown} CurrY := @CurrY - 50 {Tag delete} {DrawRec {List.drop L @CurrX} 0 @CurrX nil 10} end proc{MoveUp} CurrY := @CurrY + 50 {Tag delete} {DrawRec {List.drop L @CurrX} 0 @CurrX nil 10} end proc{DrawRec L N RealN Last MaxN} if N\=MaxN then case L of nil then skip [] H|T then Val = if {IsInt H} then H elseif {IsFloat H} then {FloatToInt H} end in if Last\=nil then {C create(line 50*(N-1) @CurrY+VSize-Last 50*N @CurrY+VSize-Val fill:black tags:Tag)} end {C create(text 50*N+15 @CurrY+VSize-Val-15 text:("("#RealN#","#Val#")") fill:red tags:Tag)} {DrawRec T N+1 RealN+1 Val MaxN} end end end in {{QTk.build td(Desc)} show} {C newTag(Tag)} % {C create(rect 10 10 190 190 fill:blue outline:red)} % {C create(text 100 100 text:"Canvas" fill:yellow)} {DrawRec L 0 0 nil 10} end % Simple Fibonacci declare fun {RecRel N MaxN Prevs} if N>MaxN then nil else This = {List.nth Prevs 1}+{List.nth Prevs 2} in This|{RecRel N+1 MaxN This|Prevs} end end {DrawGraph 200 {RecRel 0 10 [0 1]}} % What happens if we don't know how far ahead the user is going to look? % We could just pick a really big number, but how do we handle the error % case if he looks too far? It would be really complicated to throw an % exception and then somehow try to re-draw the screen... % % I know! We'll just make an INFINITE Fibonacci list! That way the % user can never go too far! declare fun lazy {RecRel N Prevs} This = {List.nth Prevs 1}+{List.nth Prevs 2} in This|{RecRel N+1 This|Prevs} end {DrawGraph 200 {RecRel 0 [0 1]}} % Okay, that was too hard to look at. Let's pick a smaller recurrence % relation. % Xk = (K + (Xk-1)*ln(K)) / (4 - Xk-2) % Let our base case be X0=0, X1 = 20. declare fun lazy {RecRel K Prevs} This = (K + {List.nth Prevs 1} * {Float.log K}) / (4.-{List.nth Prevs 2}) in This|{RecRel K+1. This|Prevs} end {DrawGraph 200 0.|20.|{RecRel 2. [0. 20.]}} % Suppose our function is something that takes a lot of effort to compute. % Even though the data structure is infinite and lazy, it is not the % same as calling a function because once a point is computed, it stays % computed. declare fun {SlowSin X} {Delay 1000} {Float.sin X} end fun lazy {RecRel K Prevs} This = 100.*{SlowSin (K*K)/100.} in This|{RecRel K+1. This|Prevs} end {DrawGraph 200 {RecRel 2. nil}}