@@ -89,6 +89,86 @@ fn chain<T, U: copy, V: copy>(res: result<T, V>, op: fn(T) -> result<U, V>)
89
89
}
90
90
}
91
91
92
+ // ______________________________________________________________________
93
+ // Note:
94
+ //
95
+ // These helper functions are written in a "pre-chained" (a.k.a,
96
+ // deforested) style because I have found that, in practice, this is
97
+ // the most concise way to do things. That means that they do not not
98
+ // terminate with a call to `ok(v)` but rather `nxt(v)`. If you would
99
+ // like to just get the result, just pass in `ok` as `nxt`.
100
+
101
+ #[ doc = "
102
+ Maps each element in the vector `ts` using the operation `op`. Should an
103
+ error occur, no further mappings are performed and the error is returned.
104
+ Should no error occur, a vector containing the result of each map is
105
+ passed to the `nxt` function.
106
+
107
+ Here is an example which increments every integer in a vector,
108
+ checking for overflow:
109
+
110
+ fn inc_conditionally(x: uint) -> result<uint,str> {
111
+ if x == uint::max_value { ret err(\" overflow\" ); }
112
+ else { ret ok(x+1u); }
113
+ }
114
+ map([1u, 2u, 3u], inc_conditionally) {|incd|
115
+ assert incd == [2u, 3u, 4u];
116
+ }
117
+
118
+ Note: if you have to combine a deforested style transform with map,
119
+ you should use `ok` for the `nxt` operation, as shown here (this is an
120
+ alternate version of the previous example where the
121
+ `inc_conditionally()` routine is deforested):
122
+
123
+ fn inc_conditionally<T>(x: uint,
124
+ nxt: fn(uint) -> result<T,str>) -> result<T,str> {
125
+ if x == uint::max_value { ret err(\" overflow\" ); }
126
+ else { ret nxt(x+1u); }
127
+ }
128
+ map([1u, 2u, 3u], inc_conditionally(_, ok)) {|incd|
129
+ assert incd == [2u, 3u, 4u];
130
+ }
131
+ " ]
132
+ fn map < T , U : copy , V : copy , W > ( ts : [ T ] ,
133
+ op : fn ( T ) -> result < V , U > ,
134
+ nxt : fn ( [ V ] ) -> result < W , U > ) -> result < W , U > {
135
+ let mut vs: [ V ] = [ ] ;
136
+ vec:: reserve ( vs, vec:: len ( ts) ) ;
137
+ for t in ts {
138
+ alt op( t) {
139
+ ok ( v) { vs += [ v] ; }
140
+ err ( u) { ret err ( u) ; }
141
+ }
142
+ }
143
+ ret nxt( vs) ;
144
+ }
145
+
146
+ #[ doc = "Same as map, but it operates over two parallel vectors.
147
+
148
+ A precondition is used here to ensure that the vectors are the same
149
+ length. While we do not often use preconditions in the standard
150
+ library, a precondition is used here because result::t is generally
151
+ used in 'careful' code contexts where it is both appropriate and easy
152
+ to accommodate an error like the vectors being of different lengths." ]
153
+ fn map2 < S , T , U : copy , V : copy , W > ( ss : [ S ] , ts : [ T ] ,
154
+ op : fn ( S , T ) -> result < V , U > ,
155
+ nxt : fn ( [ V ] ) -> result < W , U > )
156
+ : vec:: same_length( ss , ts )
157
+ -> result < W , U > {
158
+ let n = vec:: len ( ts) ;
159
+ let mut vs = [ ] ;
160
+ vec:: reserve ( vs, n) ;
161
+ let mut i = 0 u;
162
+ while i < n {
163
+ alt op( ss[ i] , ts[ i] ) {
164
+ ok ( v) { vs += [ v] ; }
165
+ err ( u) { ret err ( u) ; }
166
+ }
167
+ i += 1 u;
168
+ }
169
+ ret nxt( vs) ;
170
+ }
171
+
92
172
#[ cfg( test) ]
93
173
mod tests {
94
174
fn op1 ( ) -> result:: result < int , str > { result:: ok ( 666 ) }
0 commit comments