source: project/wiki/eggref/4/cooperative @ 34917

Last change on this file since 34917 was 34917, checked in by Mario Domenech Goulart, 3 years ago

cooperative: add "Repository" section

File size: 5.8 KB
Line 
1[[toc:]]
2== cooperative
3
4Coroutines and Finite State Machines for Chicken Scheme
5
6=== Repository
7
8[[https://github.com/yarnoiser/cooperative|https://github.com/yarnoiser/cooperative]]
9
10=== Installing
11<enscript> 
12chicken-install cooperative
13</enscript>
14
15=== Usage
16<enscript highlight="scheme">
17(use cooperative)
18</enscript>
19
20==== make-coroutine
21<procedure>(make-coroutine proc . args)</procedure>
22
23Returns a new coroutine. The resulting procedure is a thunk
24(it takes no arguments). When the coroutine is called, it is equivalent to applying
25''args'' to ''proc'', except that any calls to ''yield!''
26will return control to the calling procedure. When the coroutine is called again
27after ''yield!'', it will continue where it left off before yielding
28An error is signalled if the coroutine is called after it completes
29without calling ''yield!''.
30
31===== Example
32<enscript highlight="scheme">
33(define (from-x-to-y x y)
34  (let loop ()
35    (if (< x y)
36      (begin (yield! x)
37             (set! x (add1 x))
38             (loop))
39      y)))
40
41(define from-1-to-3 (make-coroutine from-x-to-y 1 3))
42
43(from-1-to-3)
441
45(from-1-to-3)
462
47(from-1-to-3)
483
49(from-1-to-3)
50error "coroutine has finished"
51</enscript>
52
53==== in-coroutine?
54<procedure>(in-coroutine?)</procedure>
55
56Returns true if it is called within a coroutine created with a call
57to ''make-coroutine''. Else returns false.
58
59===== Example
60<enscript highlight="scheme">
61(define (maybe-coroutine)
62  (let loop ((x 0))
63    (if (in-coroutine?)
64      (yield! 'yielded))
65    (if (= x 3)
66      x
67      (loop (add1 x)))))
68 
69  (maybe-coroutine)
70  3
71 
72  (define coroutine (make-coroutine maybe-coroutine))
73  (coroutine)
74  yielded
75  (coroutine)
76  yielded
77  (coroutine)
78  yielded
79  (coroutine)
80  yielded
81  (coroutine)
82  3
83</enscript>
84==== yield!
85
86<procedure>(yield! [val])</procedure>
87
88Exits the current coroutine returning control to the calling
89procedure. Returns the optional value ''val'', which defaults to (void). An error
90is singled if ''yield!'' is called outside of a coroutine procedure.
91
92===== Example
93See ''make-coroutine''
94
95==== fsm
96<macro>(fsm input: (input ...) vars: vars start: initial-state state ...)</macro>
97
98Creates a finite state machine. The resulting machine is a procedure which
99behaves differently with subsequent calls depending on what state it is in.
100
101The machine parameters consist of literals followed by a relevant expression.
102these parameters must be outlined in the order they are shown above.
103
104'''input: (input ...)''' A list of input values. These are received as arguments
105to the finite state machine when it is called, and can be referenced as
106variables within the state machine.
107
108'''vars: vars''' A list of variable assignments equivalent to those found
109in a ''let'' expression. These variables are internal to the state machine and
110persist between calls to it, unless specifically changed.
111
112'''start: initial-state''' The name of the initial state. This is the state in
113which the finite state machine will be in when it is first called. The name of
114the initial state is not evaluated, and does not need to be quoted.
115
116The remaining parameters are state definitions, which also consist of literals
117followed by relevant expressions. Like the above parameters, they must be
118written in the order shown:
119
120'''(state: state-name act: act output: (output ...) trans: ((condition next-state) ...))'''
121
122'''state: state-name''' The state name. This is the name of the state being
123defined and is used to refer to this state during transitions. This name is not
124evaluated, and does not need to be quoted.
125
126'''act: act''' The state's action expression. This consists
127of a single scheme expression. Forms such as ''let'' or ''begin'' should be used
128to perform multiple actions here.
129
130'''output: (output ...)''' Followed by a list of output values. A list containing all values
131specified here will be returned to the calling procedure. The list should not
132be quoted, quasiquoted or created with the list procedure, simply specified
133with parentheses, although individual elements will be evaluated.
134
135'''trans: ((condition next-state) ...)''' The state transitions list. This is an association list
136containing boolean expressions paired with states to transition to. The next time the
137finite state machine is called, it will be in the state paired with the
138first predicate to return true. The state names are not evaluated and do not
139need to be quoted.
140
141#### Example
142<enscript highlight="scheme">
143(define docking-control
144  (fsm
145    input: (use-case)
146    vars: ((ports 3) (ships 0) (status #f))
147    start: empty
148
149    (state: empty
150      act: (case use-case
151             ((arrival) (begin (set! ships (add1 ships))
152                               (set! status 'approved)))
153             ((departure) (set! status 'denied))
154             (else (error "invalid use case")))
155      output: (status)
156      trans: (((< 0 ships) else)))
157
158    (state: full
159      act: (case use-case
160             ((arrival) (set! status 'denied))
161             ((departure) (begin (set! ships (sub1 ships))
162                                 (set! status 'approved)))
163             (else (error "invalid use case")))
164      output: (status)
165      trans: (((< ships ports) else)))
166
167    (state: else
168      act: (begin (set! status 'approved)
169                  (case use-case
170                    ((arrival) (set! ships (add1 ships)))
171                    ((departure) (set! ships (sub1 ships)))
172                    (else (error "invalid use case"))))
173      output: (status)
174      trans: (((= ports ships) full)
175              ((= ships 0) empty))) ))
176
177
178(docking-control 'departure)
179(denied)
180
181(docking-control 'arrival)
182(approved)
183
184(docking-control 'arrival)
185(approved)
186
187(docking-control 'arrival)
188(approved)
189
190(docking-control 'arrival)
191(denied)
192
193(docking-control 'departure)
194(approved)
195</enscript>
196=== About the Author
197Robert Smiley, the author of this egg can be reached at yarnoiserdev@gmail.com.
Note: See TracBrowser for help on using the repository browser.