@@ -118,28 +118,18 @@ <h1 class="title">Contracts.js Documentation</h1>
118
118
< li > < a href ="#using "> < span class ="toc-section-number "> 3</ span > Using</ a > </ li >
119
119
< li > < a href ="#contracts "> < span class ="toc-section-number "> 4</ span > Contracts</ a > < ul >
120
120
< li > < a href ="#basic-contracts "> < span class ="toc-section-number "> 4.1</ span > Basic Contracts</ a > < ul >
121
- < li > < a href ="#num "> < span class ="toc-section-number "> 4.1.1</ span > < code > Num</ code > </ a > </ li >
122
- < li > < a href ="#str "> < span class ="toc-section-number "> 4.1.2</ span > < code > Str</ code > </ a > </ li >
123
- < li > < a href ="#bool "> < span class ="toc-section-number "> 4.1.3</ span > < code > Bool</ code > </ a > </ li >
124
- < li > < a href ="#odd "> < span class ="toc-section-number "> 4.1.4</ span > < code > Odd</ code > </ a > </ li >
125
- < li > < a href ="#even "> < span class ="toc-section-number "> 4.1.5</ span > < code > Even</ code > </ a > </ li >
126
- < li > < a href ="#pos "> < span class ="toc-section-number "> 4.1.6</ span > < code > Pos</ code > </ a > </ li >
127
- < li > < a href ="#nat "> < span class ="toc-section-number "> 4.1.7</ span > < code > Nat</ code > </ a > </ li >
128
- < li > < a href ="#neg "> < span class ="toc-section-number "> 4.1.8</ span > < code > Neg</ code > </ a > </ li >
129
- < li > < a href ="#any "> < span class ="toc-section-number "> 4.1.9</ span > < code > Any</ code > </ a > </ li >
130
- < li > < a href ="#none "> < span class ="toc-section-number "> 4.1.10</ span > < code > None</ code > </ a > </ li >
131
- < li > < a href ="#null "> < span class ="toc-section-number "> 4.1.11</ span > < code > Null</ code > </ a > </ li >
132
- < li > < a href ="#undefined "> < span class ="toc-section-number "> 4.1.12</ span > < code > Undefined</ code > </ a > </ li >
133
- < li > < a href ="#void "> < span class ="toc-section-number "> 4.1.13</ span > < code > Void</ code > </ a > </ li >
121
+ < li > < a href ="#custom-predicate-contracts "> < span class ="toc-section-number "> 4.1.1</ span > Custom Predicate Contracts</ a > </ li >
134
122
</ ul > </ li >
135
123
< li > < a href ="#function-contracts "> < span class ="toc-section-number "> 4.2</ span > Function Contracts</ a > < ul >
136
124
< li > < a href ="#optional-arguments "> < span class ="toc-section-number "> 4.2.1</ span > Optional Arguments</ a > </ li >
137
125
< li > < a href ="#higher-order-arguments "> < span class ="toc-section-number "> 4.2.2</ span > Higher-Order Arguments</ a > </ li >
138
- < li > < a href ="#dependent-contracts "> < span class ="toc-section-number "> 4.2.3</ span > Dependent Contracts</ a > </ li >
126
+ < li > < a href ="#contracts-on-this "> < span class ="toc-section-number "> 4.2.3</ span > Contracts on < code > this</ code > </ a > </ li >
127
+ < li > < a href ="#dependent-contracts "> < span class ="toc-section-number "> 4.2.4</ span > Dependent Contracts</ a > </ li >
139
128
</ ul > </ li >
140
129
< li > < a href ="#object-contracts "> < span class ="toc-section-number "> 4.3</ span > Object Contracts</ a > < ul >
141
130
< li > < a href ="#optional-properties "> < span class ="toc-section-number "> 4.3.1</ span > Optional Properties</ a > </ li >
142
- < li > < a href ="#proxied-objects "> < span class ="toc-section-number "> 4.3.2</ span > Proxied Objects</ a > </ li >
131
+ < li > < a href ="#method-contracts "> < span class ="toc-section-number "> 4.3.2</ span > Method Contracts</ a > </ li >
132
+ < li > < a href ="#proxied-objects "> < span class ="toc-section-number "> 4.3.3</ span > Proxied Objects</ a > </ li >
143
133
</ ul > </ li >
144
134
< li > < a href ="#array-contracts "> < span class ="toc-section-number "> 4.4</ span > Array Contracts</ a > < ul >
145
135
< li > < a href ="#repeated-fields "> < span class ="toc-section-number "> 4.4.1</ span > Repeated Fields</ a > </ li >
@@ -193,39 +183,86 @@ <h1 id="contracts"><span class="header-section-number">4</span> Contracts</h1>
193
183
blaming: (calling context for id)
194
184
*/</ code > </ pre >
195
185
< h2 id ="basic-contracts "> < span class ="header-section-number "> 4.1</ span > Basic Contracts</ h2 >
196
- < h3 id ="num "> < span class ="header-section-number "> 4.1.1</ span > < code > Num</ code > </ h3 >
197
- < p > A value that is < code > typeof</ code > number.</ p >
198
- < h3 id ="str "> < span class ="header-section-number "> 4.1.2</ span > < code > Str</ code > </ h3 >
199
- < p > A value that is < code > typeof</ code > string.</ p >
200
- < h3 id ="bool "> < span class ="header-section-number "> 4.1.3</ span > < code > Bool</ code > </ h3 >
201
- < p > A value that is < code > typeof</ code > boolean.</ p >
202
- < h3 id ="odd "> < span class ="header-section-number "> 4.1.4</ span > < code > Odd</ code > </ h3 >
203
- < p > A number that is odd (< code > val % 2 === 1</ code > ).</ p >
204
- < h3 id ="even "> < span class ="header-section-number "> 4.1.5</ span > < code > Even</ code > </ h3 >
205
- < p > A number that is even (< code > val % 2 !== 1</ code > ).</ p >
206
- < h3 id ="pos "> < span class ="header-section-number "> 4.1.6</ span > < code > Pos</ code > </ h3 >
207
- < p > A positive number (< code > val >= 0</ code > ).</ p >
208
- < h3 id ="nat "> < span class ="header-section-number "> 4.1.7</ span > < code > Nat</ code > </ h3 >
209
- < p > A natural number (< code > val > 0</ code > ).</ p >
210
- < h3 id ="neg "> < span class ="header-section-number "> 4.1.8</ span > < code > Neg</ code > </ h3 >
211
- < p > A negative number (< code > val < 0</ code > ).</ p >
212
- < h3 id ="any "> < span class ="header-section-number "> 4.1.9</ span > < code > Any</ code > </ h3 >
213
- < p > Any value.</ p >
214
- < h3 id ="none "> < span class ="header-section-number "> 4.1.10</ span > < code > None</ code > </ h3 >
215
- < p > No value (not terribly useful).</ p >
216
- < h3 id ="null "> < span class ="header-section-number "> 4.1.11</ span > < code > Null</ code > </ h3 >
217
- < p > The < code > null</ code > value.</ p >
218
- < h3 id ="undefined "> < span class ="header-section-number "> 4.1.12</ span > < code > Undefined</ code > </ h3 >
219
- < p > The < code > undefined</ code > value.</ p >
220
- < h3 id ="void "> < span class ="header-section-number "> 4.1.13</ span > < code > Void</ code > </ h3 >
221
- < p > Either < code > null</ code > or < code > undefined</ code > .</ p >
186
+ < p > Contracts.js comes with a number of basic contracts that check for first-order properties (things like < code > typeof</ code > checks).</ p >
187
+ < table >
188
+ < thead >
189
+ < tr class ="header ">
190
+ < th style ="text-align: left; "> Contract</ th >
191
+ < th style ="text-align: left; "> Description</ th >
192
+ </ tr >
193
+ </ thead >
194
+ < tbody >
195
+ < tr class ="odd ">
196
+ < td style ="text-align: left; "> < code > Num</ code > </ td >
197
+ < td style ="text-align: left; "> A value that is < code > typeof</ code > number</ td >
198
+ </ tr >
199
+ < tr class ="even ">
200
+ < td style ="text-align: left; "> < code > Str</ code > </ td >
201
+ < td style ="text-align: left; "> A value that is < code > typeof</ code > string</ td >
202
+ </ tr >
203
+ < tr class ="odd ">
204
+ < td style ="text-align: left; "> < code > Bool</ code > </ td >
205
+ < td style ="text-align: left; "> A value that is < code > typeof</ code > boolean</ td >
206
+ </ tr >
207
+ < tr class ="even ">
208
+ < td style ="text-align: left; "> < code > Odd</ code > </ td >
209
+ < td style ="text-align: left; "> A value that is odd (< code > val % 2 === 1</ code > )</ td >
210
+ </ tr >
211
+ < tr class ="odd ">
212
+ < td style ="text-align: left; "> < code > Even</ code > </ td >
213
+ < td style ="text-align: left; "> A value that is even (< code > val % 1 === 0</ code > )</ td >
214
+ </ tr >
215
+ < tr class ="even ">
216
+ < td style ="text-align: left; "> < code > Pos</ code > </ td >
217
+ < td style ="text-align: left; "> A positive number(< code > val >= 0</ code > )</ td >
218
+ </ tr >
219
+ < tr class ="odd ">
220
+ < td style ="text-align: left; "> < code > Nat</ code > </ td >
221
+ < td style ="text-align: left; "> A natural number (< code > val > 0</ code > )</ td >
222
+ </ tr >
223
+ < tr class ="even ">
224
+ < td style ="text-align: left; "> < code > Neg</ code > </ td >
225
+ < td style ="text-align: left; "> A negative number (< code > val < 0</ code > )</ td >
226
+ </ tr >
227
+ < tr class ="odd ">
228
+ < td style ="text-align: left; "> < code > Any</ code > </ td >
229
+ < td style ="text-align: left; "> Any value</ td >
230
+ </ tr >
231
+ < tr class ="even ">
232
+ < td style ="text-align: left; "> < code > None</ code > </ td >
233
+ < td style ="text-align: left; "> No value (not terribly useful)</ td >
234
+ </ tr >
235
+ < tr class ="odd ">
236
+ < td style ="text-align: left; "> < code > Null</ code > </ td >
237
+ < td style ="text-align: left; "> The < code > null</ code > value</ td >
238
+ </ tr >
239
+ < tr class ="even ">
240
+ < td style ="text-align: left; "> < code > Undefined</ code > </ td >
241
+ < td style ="text-align: left; "> The < code > undefined</ code > value</ td >
242
+ </ tr >
243
+ < tr class ="odd ">
244
+ < td style ="text-align: left; "> < code > Void</ code > </ td >
245
+ < td style ="text-align: left; "> Either < code > null</ code > or < code > undefined</ code > </ td >
246
+ </ tr >
247
+ </ tbody >
248
+ </ table >
249
+ < h3 id ="custom-predicate-contracts "> < span class ="header-section-number "> 4.1.1</ span > Custom Predicate Contracts</ h3 >
250
+ < p > All of the basic contracts are built with predicates (functions that take a single value and return a boolean) and you can make your own:</ p >
251
+ < pre class ="js "> < code > function MyNum(val) {
252
+ return typeof val === "number";
253
+ }
254
+ @ (MyNum) -> MyNum
255
+ function id(x) { return x; }</ code > </ pre >
256
+ < p > There is also ES6 arrow function shorthand syntax for defining predicate contracts inside of a function or object contract:</ p >
257
+ < pre class ="js "> < code > @ ((val) => typeof val === "function") -> Num
258
+ function id(x) { return x; }</ code > </ pre >
222
259
< h2 id ="function-contracts "> < span class ="header-section-number "> 4.2</ span > Function Contracts</ h2 >
223
260
< p > Function contracts take a comma delimited list of argument contracts and a single return value contract:</ p >
224
261
< pre class ="js "> < code > @ (Str, Num, Bool) -> Bool
225
262
function foo(s, n, b) { return b; }</ code > </ pre >
226
263
< h3 id ="optional-arguments "> < span class ="header-section-number "> 4.2.1</ span > Optional Arguments</ h3 >
227
- < p > You can make an argument optional with the < code > opt </ code > prefix:</ p >
228
- < pre class ="js "> < code > @ (Str, opt Bool) -> Str
264
+ < p > You can make an argument optional with the < code > ? </ code > prefix:</ p >
265
+ < pre class ="js "> < code > @ (Str, ? Bool) -> Str
229
266
function foo(s, b) { return s; }
230
267
231
268
foo("foo"); // fine
@@ -235,7 +272,31 @@ <h3 id="higher-order-arguments"><span class="header-section-number">4.2.2</span>
235
272
< p > You can put contracts on functions to functions. And blaming the correct party at fault even works! < a href ="what-about-blaming-modules "> Mostly</ a > .</ p >
236
273
< pre class ="js "> < code > @ (Num, (Num, Num) -> Num) -> Num
237
274
function (x, f) { return f(x, x); }</ code > </ pre >
238
- < h3 id ="dependent-contracts "> < span class ="header-section-number "> 4.2.3</ span > Dependent Contracts</ h3 >
275
+ < h3 id ="contracts-on-this "> < span class ="header-section-number "> 4.2.3</ span > Contracts on < code > this</ code > </ h3 >
276
+ < p > You can put a contract on the < code > this</ code > object of a function:</ p >
277
+ < pre class ="js "> < code > @ () -> Str
278
+ | this: {name: Str}
279
+ function f() { return this.name; }
280
+
281
+ var o = {
282
+ nam: "Bob", // typo
283
+ f: f
284
+ };
285
+ o.f();</ code > </ pre >
286
+ < p > This will let you know you did something wrong:</ p >
287
+ < pre style ="color: red ">
288
+ f: contract violation
289
+ expected: Str
290
+ given: undefined
291
+ in: the name property of
292
+ the this value of
293
+ () -> Str
294
+ | this: {name: Str}
295
+ function f guarded at line: 3
296
+ blaming: (calling context for f)
297
+ </ pre >
298
+
299
+ < h3 id ="dependent-contracts "> < span class ="header-section-number "> 4.2.4</ span > Dependent Contracts</ h3 >
239
300
< p > You can also write a function contract who's result depends on the value of its arguments.</ p >
240
301
< pre class ="js "> < code > @ (x: Pos) -> res: Num | res <= x
241
302
function square_root(x) { return Math.sqrt(x); }</ code > </ pre >
@@ -273,10 +334,37 @@ <h2 id="object-contracts"><span class="header-section-number">4.3</span> Object
273
334
< p > Note that objects are checked against their contract only once when they cross the contract barrier (in the above example this is when the < code > makePerson</ code > function returns). Basic contracts (like < code > Str</ code > and < code > Num</ code > ) are checked immediately while method contracts are deferred until the method is invoked.</ p >
274
335
< p > If you want to maintain the contract invariants throughout the object's lifetime, use < a href ="#proxied-objects "> proxied object contracts</ a > .</ p >
275
336
< h3 id ="optional-properties "> < span class ="header-section-number "> 4.3.1</ span > Optional Properties</ h3 >
276
- < p > The < code > opt </ code > prefix makes a property optional:</ p >
277
- < pre class ="js "> < code > @ ({name: Str, age: opt Num}) -> Str
337
+ < p > The < code > ? </ code > prefix makes a property optional:</ p >
338
+ < pre class ="js "> < code > @ ({name: Str, age: ? Num}) -> Str
278
339
function get Name(o) { return o.name; }</ code > </ pre >
279
- < h3 id ="proxied-objects "> < span class ="header-section-number "> 4.3.2</ span > Proxied Objects</ h3 >
340
+ < h3 id ="method-contracts "> < span class ="header-section-number "> 4.3.2</ span > Method Contracts</ h3 >
341
+ < p > Function contracts on an object contract will implicitly check that the < code > this</ code > object bound to the function obeys the object contract:</ p >
342
+ < pre class ="js "> < code > @ ({name: Str, hi: () -> Str}) -> Str
343
+ function foo(o) {
344
+ var hi = o.hi;
345
+ return hi(); // `this` is bound wrong
346
+ }
347
+
348
+ foo({
349
+ name: "Bob",
350
+ hi: function() {
351
+ return this.name;
352
+ }
353
+ })</ code > </ pre >
354
+ < p > This code will give a nice error letting us know that the < code > this</ code > object was wrong:</ p >
355
+ < pre style ="color: red ">
356
+ foo: contract violation
357
+ expected: an object with at least 2 keys
358
+ given: undefined
359
+ in: the this value of
360
+ the hi property of
361
+ the 1st argument of
362
+ ({name: Str, hi: () -> Str}) -> Str
363
+ function foo guarded at line: 2
364
+ blaming: function foo
365
+ </ pre >
366
+
367
+ < h3 id ="proxied-objects "> < span class ="header-section-number "> 4.3.3</ span > Proxied Objects</ h3 >
280
368
< p > To maintain the object contract invariant for the entire lifetime of an object, use the < code > !</ code > notation:</ p >
281
369
< pre class ="js "> < code > @ (Str, Num) -> !{name: Str, age: Num}
282
370
function makePerson(name, age) {
0 commit comments