132 lines
No EOL
130 KiB
HTML
132 lines
No EOL
130 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"/><meta name="viewport" content="width=device-width, initial-scale=0.8"/><title>7.2 Simple Contracts on Functions</title><link rel="stylesheet" type="text/css" href="../scribble.css" title="default"/><link rel="stylesheet" type="text/css" href="../racket.css" title="default"/><link rel="stylesheet" type="text/css" href="../manual-style.css" title="default"/><link rel="stylesheet" type="text/css" href="../manual-racket.css" title="default"/><link rel="stylesheet" type="text/css" href="../manual-racket.css" title="default"/><link rel="stylesheet" type="text/css" href="../doc-site.css" title="default"/><script type="text/javascript" src="../scribble-common.js"></script><script type="text/javascript" src="../manual-racket.js"></script><script type="text/javascript" src="../manual-racket.js"></script><script type="text/javascript" src="../doc-site.js"></script><script type="text/javascript" src="../local-redirect/local-redirect.js"></script><script type="text/javascript" src="../local-redirect/local-user-redirect.js"></script><!--[if IE 6]><style type="text/css">.SIEHidden { overflow: hidden; }</style><![endif]--></head><body id="doc-racket-lang-org"><div class="tocset"><div class="tocview"><div class="tocviewlist tocviewlisttopspace"><div class="tocviewtitle"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,"tocview_0");">►</a></td><td></td><td><a href="index.html" class="tocviewlink" data-pltdoc="x">The Racket Guide</a></td></tr></table></div><div class="tocviewsublisttop" style="display: none;" id="tocview_0"><table cellspacing="0" cellpadding="0"><tr><td align="right">1 </td><td><a href="intro.html" class="tocviewlink" data-pltdoc="x">Welcome to Racket</a></td></tr><tr><td align="right">2 </td><td><a href="to-scheme.html" class="tocviewlink" data-pltdoc="x">Racket Essentials</a></td></tr><tr><td align="right">3 </td><td><a href="datatypes.html" class="tocviewlink" data-pltdoc="x">Built-<wbr></wbr>In Datatypes</a></td></tr><tr><td align="right">4 </td><td><a href="scheme-forms.html" class="tocviewlink" data-pltdoc="x">Expressions and Definitions</a></td></tr><tr><td align="right">5 </td><td><a href="define-struct.html" class="tocviewlink" data-pltdoc="x">Programmer-<wbr></wbr>Defined Datatypes</a></td></tr><tr><td align="right">6 </td><td><a href="modules.html" class="tocviewlink" data-pltdoc="x">Modules</a></td></tr><tr><td align="right">7 </td><td><a href="contracts.html" class="tocviewselflink" data-pltdoc="x">Contracts</a></td></tr><tr><td align="right">8 </td><td><a href="i_o.html" class="tocviewlink" data-pltdoc="x">Input and Output</a></td></tr><tr><td align="right">9 </td><td><a href="regexp.html" class="tocviewlink" data-pltdoc="x">Regular Expressions</a></td></tr><tr><td align="right">10 </td><td><a href="control.html" class="tocviewlink" data-pltdoc="x">Exceptions and Control</a></td></tr><tr><td align="right">11 </td><td><a href="for.html" class="tocviewlink" data-pltdoc="x">Iterations and Comprehensions</a></td></tr><tr><td align="right">12 </td><td><a href="match.html" class="tocviewlink" data-pltdoc="x">Pattern Matching</a></td></tr><tr><td align="right">13 </td><td><a href="classes.html" class="tocviewlink" data-pltdoc="x">Classes and Objects</a></td></tr><tr><td align="right">14 </td><td><a href="units.html" class="tocviewlink" data-pltdoc="x">Units</a></td></tr><tr><td align="right">15 </td><td><a href="reflection.html" class="tocviewlink" data-pltdoc="x">Reflection and Dynamic Evaluation</a></td></tr><tr><td align="right">16 </td><td><a href="macros.html" class="tocviewlink" data-pltdoc="x">Macros</a></td></tr><tr><td align="right">17 </td><td><a href="languages.html" class="tocviewlink" data-pltdoc="x">Creating Languages</a></td></tr><tr><td align="right">18 </td><td><a href="concurrency.html" class="tocviewlink" data-pltdoc="x">Concurrency and Synchronization</a></td></tr><tr><td align="right">19 </td><td><a href="performance.html" class="tocviewlink" data-pltdoc="x">Performance</a></td></tr><tr><td align="right">20 </td><td><a href="parallelism.html" class="tocviewlink" data-pltdoc="x">Parallelism</a></td></tr><tr><td align="right">21 </td><td><a href="running.html" class="tocviewlink" data-pltdoc="x">Running and Creating Executables</a></td></tr><tr><td align="right">22 </td><td><a href="More_Libraries.html" class="tocviewlink" data-pltdoc="x">More Libraries</a></td></tr><tr><td align="right">23 </td><td><a href="dialects.html" class="tocviewlink" data-pltdoc="x">Dialects of Racket and Scheme</a></td></tr><tr><td align="right">24 </td><td><a href="other-editors.html" class="tocviewlink" data-pltdoc="x">Command-<wbr></wbr>Line Tools and Your Editor of Choice</a></td></tr><tr><td align="right"></td><td><a href="doc-bibliography.html" class="tocviewlink" data-pltdoc="x">Bibliography</a></td></tr><tr><td align="right"></td><td><a href="doc-index.html" class="tocviewlink" data-pltdoc="x">Index</a></td></tr></table></div></div><div class="tocviewlist"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,"tocview_1");">▼</a></td><td>7 </td><td><a href="contracts.html" class="tocviewlink" data-pltdoc="x">Contracts</a></td></tr></table><div class="tocviewsublist" style="display: block;" id="tocview_1"><table cellspacing="0" cellpadding="0"><tr><td align="right">7.1 </td><td><a href="contract-boundaries.html" class="tocviewlink" data-pltdoc="x">Contracts and Boundaries</a></td></tr><tr><td align="right">7.2 </td><td><a href="contract-func.html" class="tocviewselflink" data-pltdoc="x">Simple Contracts on Functions</a></td></tr><tr><td align="right">7.3 </td><td><a href="contracts-general-functions.html" class="tocviewlink" data-pltdoc="x">Contracts on Functions in General</a></td></tr><tr><td align="right">7.4 </td><td><a href="contracts-first.html" class="tocviewlink" data-pltdoc="x">Contracts:<span class="mywbr"> </span> A Thorough Example</a></td></tr><tr><td align="right">7.5 </td><td><a href="contracts-struct.html" class="tocviewlink" data-pltdoc="x">Contracts on Structures</a></td></tr><tr><td align="right">7.6 </td><td><a href="contracts-exists.html" class="tocviewlink" data-pltdoc="x">Abstract Contracts using <span class="RktPn">#:<span class="mywbr"> </span>exists</span> and <span class="RktPn">#:<span class="mywbr"> </span>∃</span></a></td></tr><tr><td align="right">7.7 </td><td><a href="contracts-examples.html" class="tocviewlink" data-pltdoc="x">Additional Examples</a></td></tr><tr><td align="right">7.8 </td><td><a href="Building_New_Contracts.html" class="tocviewlink" data-pltdoc="x">Building New Contracts</a></td></tr><tr><td align="right">7.9 </td><td><a href="contracts-gotchas.html" class="tocviewlink" data-pltdoc="x">Gotchas</a></td></tr></table></div></div><div class="tocviewlist"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,"tocview_2");">►</a></td><td>7.2 </td><td><a href="contract-func.html" class="tocviewselflink" data-pltdoc="x">Simple Contracts on Functions</a></td></tr></table><div class="tocviewsublistbottom" style="display: none;" id="tocview_2"><table cellspacing="0" cellpadding="0"><tr><td align="right">7.2.1 </td><td><a href="contract-func.html#%28part._.Styles_of_-_%29" class="tocviewlink" data-pltdoc="x">Styles of <span class="RktSym"><span class="RktStxLink"><span class="nobreak">-<wbr></wbr>></span></span></span></a></td></tr><tr><td align="right">7.2.2 </td><td><a href="contract-func.html#%28part._simple-nested%29" class="tocviewlink" data-pltdoc="x">Using <span class="RktSym"><span class="RktStxLink">define/<span class="mywbr"> </span>contract</span></span> and <span class="RktSym"><span class="RktStxLink"><span class="nobreak">-<wbr></wbr>></span></span></span></a></td></tr><tr><td align="right">7.2.3 </td><td><a href="contract-func.html#%28part._any_and_any_c%29" class="tocviewlink" data-pltdoc="x"><span class="RktSym"><span class="RktStxLink">any</span></span> and <span class="RktSym"><span class="RktValLink">any/<span class="mywbr"> </span>c</span></span></a></td></tr><tr><td align="right">7.2.4 </td><td><a href="contract-func.html#%28part._contracts-own%29" class="tocviewlink" data-pltdoc="x">Rolling Your Own Contracts</a></td></tr><tr><td align="right">7.2.5 </td><td><a href="contract-func.html#%28part._.Contracts_on_.Higher-order_.Functions%29" class="tocviewlink" data-pltdoc="x">Contracts on Higher-<wbr></wbr>order Functions</a></td></tr><tr><td align="right">7.2.6 </td><td><a href="contract-func.html#%28part._contracts-flat-named-contracts%29" class="tocviewlink" data-pltdoc="x">Contract Messages with “???”</a></td></tr><tr><td align="right">7.2.7 </td><td><a href="contract-func.html#%28part._contracts-dissecting-contract-errors%29" class="tocviewlink" data-pltdoc="x">Dissecting a contract error message</a></td></tr></table></div></div></div><div class="tocsub"><div class="tocsubtitle">On this page:</div><table class="tocsublist" cellspacing="0"><tr><td><span class="tocsublinknumber">7.2.1<tt> </tt></span><a href="contract-func.html#%28part._.Styles_of_-_%29" class="tocsubseclink" data-pltdoc="x">Styles of <span class="RktSym"><span class="RktStxLink"><span class="nobreak">-<wbr></wbr>></span></span></span></a></td></tr><tr><td><span class="tocsublinknumber">7.2.2<tt> </tt></span><a href="contract-func.html#%28part._simple-nested%29" class="tocsubseclink" data-pltdoc="x">Using <span class="RktSym"><span class="RktStxLink">define/<span class="mywbr"> </span>contract</span></span> and <span class="RktSym"><span class="RktStxLink"><span class="nobreak">-<wbr></wbr>></span></span></span></a></td></tr><tr><td><span class="tocsublinknumber">7.2.3<tt> </tt></span><a href="contract-func.html#%28part._any_and_any_c%29" class="tocsubseclink" data-pltdoc="x"><span class="RktSym"><span class="RktStxLink">any</span></span> and <span class="RktSym"><span class="RktValLink">any/<span class="mywbr"> </span>c</span></span></a></td></tr><tr><td><span class="tocsublinknumber">7.2.4<tt> </tt></span><a href="contract-func.html#%28part._contracts-own%29" class="tocsubseclink" data-pltdoc="x">Rolling Your Own Contracts</a></td></tr><tr><td><span class="tocsublinknumber">7.2.5<tt> </tt></span><a href="contract-func.html#%28part._.Contracts_on_.Higher-order_.Functions%29" class="tocsubseclink" data-pltdoc="x">Contracts on Higher-<wbr></wbr>order Functions</a></td></tr><tr><td><span class="tocsublinknumber">7.2.6<tt> </tt></span><a href="contract-func.html#%28part._contracts-flat-named-contracts%29" class="tocsubseclink" data-pltdoc="x">Contract Messages with “???”</a></td></tr><tr><td><span class="tocsublinknumber">7.2.7<tt> </tt></span><a href="contract-func.html#%28part._contracts-dissecting-contract-errors%29" class="tocsubseclink" data-pltdoc="x">Dissecting a contract error message</a></td></tr></table></div></div><div class="maincolumn"><div class="main"><div class="navsettop"><span class="navleft"><form class="searchform"><input class="searchbox" id="searchbox" type="text" tabindex="1" placeholder="...search manuals..." title="Enter a search string to search the manuals" onkeypress="return DoSearchKey(event, this, "8.6", "../");"/></form> <a href="https://download.racket-lang.org/releases/8.6/doc/index.html" title="up to the documentation top" data-pltdoc="x" onclick="return GotoPLTRoot("8.6");">top</a><span class="tocsettoggle"> <a href="javascript:void(0);" title="show/hide table of contents" onclick="TocsetToggle();">contents</a></span></span><span class="navright"> <a href="contract-boundaries.html" title="backward to "7.1 Contracts and Boundaries"" data-pltdoc="x">← prev</a> <a href="contracts.html" title="up to "7 Contracts"" data-pltdoc="x">up</a> <a href="contracts-general-functions.html" title="forward to "7.3 Contracts on Functions in General"" data-pltdoc="x">next →</a></span> </div><h4 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""contract-func"">7.2<tt> </tt><a name="(part._contract-func)"></a>Simple Contracts on Functions</h4><p>A mathematical function has a <a name="(tech._domain)"></a><span style="font-style: italic">domain</span> and a
|
|
<a name="(tech._range)"></a><span style="font-style: italic">range</span>. The domain indicates the kind of values that the
|
|
function can accept as arguments, and the range indicates the kind of
|
|
values that it produces. The conventional notation for describing a
|
|
function with its domain and range is</p><blockquote class="SCodeFlow"><p><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">:</span><span class="hspace"> </span><span class="RktSym">A</span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym">B</span></p></blockquote><p>where <span class="RktSym">A</span> is the domain of the function and <span class="RktSym">B</span> is the
|
|
range.</p><p>Functions in a programming language have domains and ranges, too, and
|
|
a contract can ensure that a function receives only values in its
|
|
domain and produces only values in its range. A <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span> creates
|
|
such a contract for a function. The forms after a <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span> specify
|
|
contracts for the domains and finally a contract for the range.</p><p>Here is a module that might represent a bank account:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><a href="Module_Syntax.html#%28part._hash-lang%29" class="RktModLink" data-pltdoc="x"><span class="RktMod">#lang</span></a><span class="hspace"> </span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=index.html&version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket</span></a></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._provide%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">provide</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._contract-out%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">contract-out</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">deposit</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._number%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">number?</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">balance</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._number%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">number?</a></span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">amount</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">deposit</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span><span class="hspace"> </span><span class="RktSym">amount</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">amount</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">balance</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">amount</span><span class="RktPn">)</span></td></tr></table></blockquote><p>The module exports two functions:</p><ul><li><p><span class="RktSym">deposit</span>, which accepts a number and returns some value
|
|
that is not specified in the contract, and</p></li><li><p><span class="RktSym">balance</span>, which returns a number indicating the current
|
|
balance of the account.</p></li></ul><p>When a module exports a function, it establishes two channels of
|
|
communication between itself as a “server” and the “client” module
|
|
that imports the function. If the client module calls the function, it
|
|
sends a value into the server module. Conversely, if such a function
|
|
call ends and the function returns a value, the server module sends a
|
|
value back to the client module. This client–server distinction is
|
|
important, because when something goes wrong, one or the other of the
|
|
parties is to blame.</p><p>If a client module were to apply <span class="RktSym">deposit</span> to <span class="RktVal">'</span><span class="RktVal">millions</span>,
|
|
it would violate the contract. The contract-monitoring system would
|
|
catch this violation and blame the client for breaking the contract with
|
|
the above module. In contrast, if the <span class="RktSym">balance</span> function were
|
|
to return <span class="RktVal">'</span><span class="RktVal">broke</span>, the contract-monitoring system
|
|
would blame the server module.</p><p>A <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span> by itself is not a contract; it is a <a name="(tech._contract._combinator)"></a><span style="font-style: italic">contract
|
|
combinator</span>, which combines other contracts to form a contract.</p><h5 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""Styles_of_-_"">7.2.1<tt> </tt><a name="(part._.Styles_of_-_)"></a>Styles of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span></h5><p>If you are used to mathematical functions, you may prefer a contract
|
|
arrow to appear between the domain and the range of a function, not
|
|
at the beginning. If you have read <span style="font-style: italic"><a href="https://htdp.org">How to Design Programs</a></span>, you have seen this many
|
|
times. Indeed, you may have seen contracts such as these in other
|
|
people’s code:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._provide%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">provide</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._contract-out%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">contract-out</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">deposit</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._number%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">number?</a></span><span class="hspace"> </span><span class="RktPn">. </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="RktPn"> .</span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>If a Racket S-expression contains two dots with a symbol in the middle,
|
|
the reader re-arranges the S-expression and place the symbol at the front,
|
|
as described in <a href="Pairs__Lists__and_Racket_Syntax.html#%28part._lists-and-syntax%29" data-pltdoc="x">Lists and Racket Syntax</a>. Thus,</p><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._number%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">number?</a></span><span class="hspace"> </span><span class="RktPn">. </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="RktPn"> .</span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span><span class="RktPn">)</span></p></blockquote><p>is just another way of writing</p><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._number%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">number?</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span><span class="RktPn">)</span></p></blockquote><h5 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""simple-nested"">7.2.2<tt> </tt><a name="(part._simple-nested)"></a>Using <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fregion..rkt%2529._define%252Fcontract%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/contract</a></span> and <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span></h5><p>The <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fregion..rkt%2529._define%252Fcontract%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/contract</a></span> form introduced in <a href="contract-boundaries.html#%28part._contracts-intro-nested%29" data-pltdoc="x">Experimenting with Nested Contract Boundaries</a> can
|
|
also be used to define functions that come with a contract. For example,</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fregion..rkt%2529._define%252Fcontract%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/contract</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">deposit</span><span class="hspace"> </span><span class="RktSym">amount</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._number%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">number?</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">implementation goes here</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">....</span><span class="RktPn">)</span></td></tr></table></blockquote><p>which defines the <span class="RktSym">deposit</span> function with the contract from earlier.
|
|
Note that this has two potentially important impacts on the use of
|
|
<span class="RktSym">deposit</span>:</p><ol><li><p>The contract will be checked on any call to <span class="RktSym">deposit</span>
|
|
that is outside of the definition of <span class="RktSym">deposit</span> –
|
|
even those inside the module in which it is defined. Because
|
|
there may be many calls inside the module, this checking may cause
|
|
the contract to be checked too often, which could lead to
|
|
a performance degradation. This is especially true if the function
|
|
is called repeatedly from a loop.</p></li><li><p>In some situations, a function may be written to accept a more
|
|
lax set of inputs when called by other code in the same module.
|
|
For such use cases, the contract boundary established by
|
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fregion..rkt%2529._define%252Fcontract%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define/contract</a></span> is too strict.</p></li></ol><h5 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""any_and_any_c"">7.2.3<tt> </tt><a name="(part._any_and_any_c)"></a><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span> and <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">any/c</a></span></h5><p>The <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span> contract used for <span class="RktSym">deposit</span> matches any kind
|
|
of result, and it can only be used in the range position of a function
|
|
contract. Instead of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span> above, we could use the more
|
|
specific contract <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=void.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._void%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">void?</a></span>, which says that the function will
|
|
always return the <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=void.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._void%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">void</a></span><span class="RktPn">)</span> value. The <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=void.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._void%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">void?</a></span> contract,
|
|
however, would require the contract monitoring system to check the
|
|
return value every time the function is called, even though the
|
|
“client” module can’t do much with the value. In contrast,
|
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span> tells the monitoring system <span style="font-style: italic">not</span> to check the
|
|
return value, it tells a potential client that the “server” module
|
|
<span style="font-style: italic">makes no promises at all</span> about the function’s return value,
|
|
even whether it is a single value or multiple values.</p><p>The <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">any/c</a></span> contract is similar to <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span>, in that it
|
|
makes no demands on a value. Unlike <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span>, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">any/c</a></span>
|
|
indicates a single value, and it is suitable for use as an argument
|
|
contract. Using <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">any/c</a></span> as a range contract imposes a check
|
|
that the function produces a single value. That is,</p><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._integer%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">integer?</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span><span class="RktPn">)</span></p></blockquote><p>describes a function that accepts an integer and returns any number of
|
|
values, while</p><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._integer%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">integer?</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">any/c</a></span><span class="RktPn">)</span></p></blockquote><p>describes a function that accepts an integer and produces a single
|
|
result (but does not say anything more about the result). The function</p><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=values.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._values%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">values</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._-%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote><p>matches <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="stt"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._integer%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">integer?</a></span><span class="stt"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span><span class="RktPn">)</span>, but not <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="stt"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._integer%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">integer?</a></span><span class="stt"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">any/c</a></span><span class="RktPn">)</span>.</p><p>Use <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">any/c</a></span> as a result contract when it is particularly
|
|
important to promise a single result from a function. Use <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span>
|
|
when you want to promise as little as possible (and incur as little
|
|
checking as possible) for a function’s result.</p><h5 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""contracts-own"">7.2.4<tt> </tt><a name="(part._contracts-own)"></a>Rolling Your Own Contracts</h5><p>The <span class="RktSym">deposit</span> function adds the given number to the value of
|
|
<span class="RktSym">amount</span>. While the function’s contract prevents clients from
|
|
applying it to non-numbers, the contract still allows them to apply
|
|
the function to complex numbers, negative numbers, or inexact numbers,
|
|
none of which sensibly represent amounts of money.</p><p>The contract system allows programmers to define their own contracts
|
|
as functions:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><a href="Module_Syntax.html#%28part._hash-lang%29" class="RktModLink" data-pltdoc="x"><span class="RktMod">#lang</span></a><span class="hspace"> </span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=index.html&version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket</span></a></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">amount?</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=if.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._and%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._number%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">number?</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._integer%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">integer?</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._exact%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">exact?</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%7E3e%7E3d%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">>=</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._provide%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">provide</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._contract-out%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">contract-out</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">an amount is a natural number of cents</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">is the given number an amount?</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">deposit</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym">amount?</span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">amount?</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">any/c</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=booleans.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._boolean%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">boolean?</a></span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">balance</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym">amount?</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">amount</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">deposit</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span><span class="hspace"> </span><span class="RktSym">amount</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">amount</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">balance</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">amount</span><span class="RktPn">)</span></td></tr></table></blockquote><p>This module defines an <span class="RktSym">amount?</span> function and uses it as a
|
|
contract within <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span> contracts. When a client calls the
|
|
<span class="RktSym">deposit</span> function as exported with the contract <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="stt"> </span><span class="RktSym">amount?</span><span class="stt"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span><span class="RktPn">)</span>, it must supply an exact, nonnegative integer, otherwise
|
|
the <span class="RktSym">amount?</span> function applied to the argument will return
|
|
<span class="RktVal">#f</span>, which will cause the contract-monitoring system to blame
|
|
the client. Similarly, the server module must provide an exact,
|
|
nonnegative integer as the result of <span class="RktSym">balance</span> to remain
|
|
blameless.</p><p>Of course, it makes no sense to restrict a channel of communication to
|
|
values that the client doesn’t understand. Therefore the module also
|
|
exports the <span class="RktSym">amount?</span> predicate itself, with a contract saying
|
|
that it accepts an arbitrary value and returns a boolean.</p><p>In this case, we could also have used <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._natural-number%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">natural-number/c</a></span> in
|
|
place of <span class="RktSym">amount?</span>, since it implies exactly the same check:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._provide%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">provide</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._contract-out%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">contract-out</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">deposit</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._natural-number%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">natural-number/c</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">balance</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._natural-number%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">natural-number/c</a></span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>Every function that accepts one argument can be treated as a predicate
|
|
and thus used as a contract. For combining existing checks into a new
|
|
one, however, contract combinators such as <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._and%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">and/c</a></span> and
|
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._or%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">or/c</a></span> are often useful. For example, here is yet another way
|
|
to write the contracts above:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">amount/c</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._and%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">and/c</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._number%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">number?</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._integer%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">integer?</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._exact%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">exact?</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._or%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">or/c</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._positive%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">positive?</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._provide%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">provide</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._contract-out%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">contract-out</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">deposit</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym">amount/c</span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">balance</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym">amount/c</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>Other values also serve double duty as contracts. For example, if a
|
|
function accepts a number or <span class="RktVal">#f</span>, <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._or%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">or/c</a></span><span class="stt"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._number%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">number?</a></span><span class="stt"> </span><span class="RktVal">#f</span><span class="RktPn">)</span>
|
|
suffices. Similarly, the <span class="RktSym">amount/c</span> contract could have been
|
|
written with a <span class="RktVal">0</span> in place of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span>. If you use a
|
|
regular expression as a contract, the contract accepts strings and
|
|
byte strings that match the regular expression.</p><p>Naturally, you can mix your own contract-implementing functions with
|
|
combinators like <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._and%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">and/c</a></span>. Here is a module for creating strings
|
|
from banking records:</p><p><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><a href="Module_Syntax.html#%28part._hash-lang%29" class="RktModLink" data-pltdoc="x"><span class="RktMod">#lang</span></a><span class="hspace"> </span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=index.html&version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket</span></a></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">has-decimal?</span><span class="hspace"> </span><span class="RktSym">str</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">L</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=strings.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._string-length%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">string-length</a></span><span class="hspace"> </span><span class="RktSym">str</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=if.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._and%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%7E3e%7E3d%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">>=</a></span><span class="hspace"> </span><span class="RktSym">L</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=characters.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._char%7E3d%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">char=?</a></span><span class="hspace"> </span><span class="RktVal">#\.</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=strings.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._string-ref%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">string-ref</a></span><span class="hspace"> </span><span class="RktSym">str</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._-%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktSym">L</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._provide%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">provide</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._contract-out%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">contract-out</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">convert a random number to a string</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">format-number</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._number%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">number?</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=strings.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._string%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">string?</a></span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">convert an amount into a string with a decimal</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">point, as in an amount of US currency</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">format-nat</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._natural-number%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">natural-number/c</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._and%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">and/c</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=strings.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._string%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">string?</a></span><span class="hspace"> </span><span class="RktSym">has-decimal?</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The contract of the exported function <span class="RktSym">format-number</span> specifies
|
|
that the function consumes a number and produces a string. The
|
|
contract of the exported function <span class="RktSym">format-nat</span> is more
|
|
interesting than the one of <span class="RktSym">format-number</span>. It consumes only
|
|
natural numbers. Its range contract promises a string that has a
|
|
<span class="RktInBG"><span class="hspace"></span><span class="RktIn">.</span><span class="hspace"></span></span> in the third position from the right.</div></p><p>If we want to strengthen the promise of the range contract for
|
|
<span class="RktSym">format-nat</span> so that it admits only strings with digits and a single
|
|
dot, we could write it like this:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><a href="Module_Syntax.html#%28part._hash-lang%29" class="RktModLink" data-pltdoc="x"><span class="RktMod">#lang</span></a><span class="hspace"> </span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=index.html&version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket</span></a></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">digit-char?</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._member%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">member</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">#\1</span><span class="hspace"> </span><span class="RktVal">#\2</span><span class="hspace"> </span><span class="RktVal">#\3</span><span class="hspace"> </span><span class="RktVal">#\4</span><span class="hspace"> </span><span class="RktVal">#\5</span><span class="hspace"> </span><span class="RktVal">#\6</span><span class="hspace"> </span><span class="RktVal">#\7</span><span class="hspace"> </span><span class="RktVal">#\8</span><span class="hspace"> </span><span class="RktVal">#\9</span><span class="hspace"> </span><span class="RktVal">#\0</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">has-decimal?</span><span class="hspace"> </span><span class="RktSym">str</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">L</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=strings.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._string-length%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">string-length</a></span><span class="hspace"> </span><span class="RktSym">str</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=if.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._and%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%7E3e%7E3d%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">>=</a></span><span class="hspace"> </span><span class="RktSym">L</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=characters.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._char%7E3d%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">char=?</a></span><span class="hspace"> </span><span class="RktVal">#\.</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=strings.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._string-ref%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">string-ref</a></span><span class="hspace"> </span><span class="RktSym">str</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._-%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktSym">L</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">is-decimal-string?</span><span class="hspace"> </span><span class="RktSym">str</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">L</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=strings.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._string-length%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">string-length</a></span><span class="hspace"> </span><span class="RktSym">str</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=if.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._and%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">has-decimal?</span><span class="hspace"> </span><span class="RktSym">str</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fmap..rkt%2529._andmap%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">andmap</a></span><span class="hspace"> </span><span class="RktSym">digit-char?</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=strings.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._string-%7E3elist%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">string->list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=strings.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._substring%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">substring</a></span><span class="hspace"> </span><span class="RktSym">str</span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._-%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktSym">L</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fmap..rkt%2529._andmap%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">andmap</a></span><span class="hspace"> </span><span class="RktSym">digit-char?</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=strings.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._string-%7E3elist%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">string->list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=strings.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._substring%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">substring</a></span><span class="hspace"> </span><span class="RktSym">str</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._-%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktSym">L</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">L</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktSym">....</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._provide%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">provide</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._contract-out%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">contract-out</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">....</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">convert an amount (natural number) of cents</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">into a dollar-based string</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">format-nat</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._natural-number%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">natural-number/c</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._and%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">and/c</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=strings.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._string%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">string?</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">is-decimal-string?</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>Alternately, in this case, we could use a regular expression as a
|
|
contract:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><a href="Module_Syntax.html#%28part._hash-lang%29" class="RktModLink" data-pltdoc="x"><span class="RktMod">#lang</span></a><span class="hspace"> </span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=index.html&version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket</span></a></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._provide%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">provide</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._contract-out%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">contract-out</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">....</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">convert an amount (natural number) of cents</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">into a dollar-based string</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">format-nat</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._natural-number%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">natural-number/c</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._and%252Fc%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">and/c</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=strings.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._string%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">string?</a></span><span class="hspace"> </span><span class="RktVal">#rx"[0-9]*\\.[0-9][0-9]"</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><h5 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""Contracts_on_Higher-order_Functions"">7.2.5<tt> </tt><a name="(part._.Contracts_on_.Higher-order_.Functions)"></a>Contracts on Higher-order Functions</h5><p>Function contracts are not just restricted to having simple
|
|
predicates on their domains or ranges. Any of the contract
|
|
combinators discussed here, including function contracts
|
|
themselves, can be used as contracts on the arguments and
|
|
results of a function.</p><p>For example,</p><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._integer%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">integer?</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._integer%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">integer?</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._integer%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">integer?</a></span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote><p>is a contract that describes a curried function. It matches functions
|
|
that accept one argument and then return another function accepting a
|
|
second argument before finally returning an integer. If a server
|
|
exports a function <span class="RktSym">make-adder</span> with this contract, and if
|
|
<span class="RktSym">make-adder</span> returns a value other than a function, then the
|
|
server is to blame. If <span class="RktSym">make-adder</span> does return a function, but
|
|
the resulting function is applied to a value other than an integer,
|
|
then the client is to blame.</p><p>Similarly, the contract</p><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._integer%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">integer?</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._integer%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">integer?</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._integer%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">integer?</a></span><span class="RktPn">)</span></p></blockquote><p>describes functions that accept other functions as its input. If a
|
|
server exports a function <span class="RktSym">twice</span> with this contract and the
|
|
<span class="RktSym">twice</span> is applied to a value other than a function of one
|
|
argument, then the client is to blame. If <span class="RktSym">twice</span> is applied to
|
|
a function of one argument and <span class="RktSym">twice</span> calls the given function
|
|
on a value other than an integer, then the server is to blame.</p><h5 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""contracts-flat-named-contracts"">7.2.6<tt> </tt><a name="(part._contracts-flat-named-contracts)"></a>Contract Messages with “???”</h5><p><div class="SIntrapara">You wrote your module. You added contracts. You put them into the interface
|
|
so that client programmers have all the information from interfaces. It’s a
|
|
piece of art:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=module.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._module%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">module</a></span><span class="hspace"> </span><span class="RktSym">bank-server</span><span class="hspace"> </span><span class="RktSym">racket</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._provide%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">provide</a></span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._contract-out%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">contract-out</a></span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">deposit</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._%7Ece%7Ebb%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">λ</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=if.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._and%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._number%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">number?</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._integer%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">integer?</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%7E3e%7E3d%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">>=</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">total</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">deposit</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span><span class="hspace"> </span><span class="RktSym">total</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">total</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote></div></p><p>Several clients used your module. Others used their
|
|
modules in turn. And all of a sudden one of them sees this error
|
|
message:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._require%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">require</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">bank-server</span><span class="RktPn">)</span></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">deposit</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span>0</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">deposit: contract violation</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">expected: ???</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">given: -10</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">in: the 1st argument of</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">(-> ??? any)</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">contract from: bank-server</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">blaming: top-level</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">(assuming the contract is correct)</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">at: eval:2:0</span></p></td></tr></table></blockquote><p>What is the <span class="RktErr">???</span> doing there? Wouldn’t it be nice if
|
|
we had a name for this class of data much like we have string, number,
|
|
and so on?</p><p>For this situation, Racket provides <a name="(tech._flat._named._contract)"></a><span style="font-style: italic">flat named
|
|
contracts</span>. The use of “contract” in this term shows that contracts
|
|
are first-class values. The “flat” means that the collection of data
|
|
is a subset of the built-in atomic classes of data; they are described
|
|
by a predicate that consumes all Racket values and produces a
|
|
boolean. The “named” part says what we want to do, which is to name
|
|
the contract so that error messages become intelligible:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=module.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._module%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">module</a></span><span class="hspace"> </span><span class="RktSym">improved-bank-server</span><span class="hspace"> </span><span class="RktSym">racket</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._provide%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">provide</a></span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=attaching-contracts-to-values.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._contract-out%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">contract-out</a></span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">deposit</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=function-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fbase..rkt%2529._-%7E3e%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x"><span class="nobreak">-></span></a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528def._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._flat-named-contract%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">flat-named-contract</a></span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">amount</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._%7Ece%7Ebb%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">λ</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=if.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._and%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._number%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">number?</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._integer%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">integer?</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%7E3e%7E3d%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">>=</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=data-structure-contracts.html%23%2528form._%2528%2528lib._racket%252Fcontract%252Fprivate%252Fmisc..rkt%2529._any%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">any</a></span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">total</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">deposit</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span><span class="hspace"> </span><span class="RktSym">total</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">total</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote><p>With this little change, the error message becomes quite readable:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._require%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">require</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">improved-bank-server</span><span class="RktPn">)</span></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">deposit</span><span class="hspace"> </span><span class="RktVal"><span class="nobreak">-1</span>0</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktErr">deposit: contract violation</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">expected: amount</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">given: -10</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">in: the 1st argument of</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">(-> amount any)</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">contract from: improved-bank-server</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">blaming: top-level</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">(assuming the contract is correct)</span></p></td></tr><tr><td><p><span class="RktErr"></span><span class="hspace"> </span><span class="RktErr">at: eval:5:0</span></p></td></tr></table></blockquote><h5 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""contracts-dissecting-contract-errors"">7.2.7<tt> </tt><a name="(part._contracts-dissecting-contract-errors)"></a>Dissecting a contract error message</h5><p><div class="SIntrapara">In general, each contract error message consists of six sections:
|
|
</div><div class="SIntrapara"><ul><li><p><div class="SIntrapara">a name for the function or method associated with the contract
|
|
and either the phrase “contract violation” or “broke its contract”
|
|
depending on whether the contract was violated by the client or the
|
|
server; e.g. in the previous example: </div><div class="SIntrapara"><table cellspacing="0" cellpadding="0"><tr><td><p class="RktErr">deposit: contract violation</p></td></tr></table></div></p></li><li><p><div class="SIntrapara">a description of the precise aspect of the contract that was violated, </div><div class="SIntrapara"><table cellspacing="0" cellpadding="0"><tr><td><p class="RktErr"> expected: amount</p></td></tr><tr><td><p class="RktErr"> given: -10</p></td></tr></table></div></p></li><li><p><div class="SIntrapara">the complete contract plus a path into it showing which aspect was violated, </div><div class="SIntrapara"><table cellspacing="0" cellpadding="0"><tr><td><p class="RktErr"> in: the 1st argument of</p></td></tr><tr><td><p class="RktErr"> (-> amount any)</p></td></tr></table></div></p></li><li><p><div class="SIntrapara">the module where the contract was put (or, more generally, the boundary that the contract mediates), </div><div class="SIntrapara"><table cellspacing="0" cellpadding="0"><tr><td><p class="RktErr"> contract from: improved-bank-server</p></td></tr></table></div></p></li><li><p><div class="SIntrapara">who was blamed, </div><div class="SIntrapara"><table cellspacing="0" cellpadding="0"><tr><td><p class="RktErr"> blaming: top-level</p></td></tr><tr><td><p class="RktErr"> (assuming the contract is correct)</p></td></tr></table></div></p></li><li><p><div class="SIntrapara">and the source location where the contract appears. </div><div class="SIntrapara"><table cellspacing="0" cellpadding="0"><tr><td><p class="RktErr"> at: eval:5:0</p></td></tr></table></div></p></li></ul></div></p><div class="navsetbottom"><span class="navleft"><form class="searchform"><input class="searchbox" id="searchbox" type="text" tabindex="1" placeholder="...search manuals..." title="Enter a search string to search the manuals" onkeypress="return DoSearchKey(event, this, "8.6", "../");"/></form> <a href="https://download.racket-lang.org/releases/8.6/doc/index.html" title="up to the documentation top" data-pltdoc="x" onclick="return GotoPLTRoot("8.6");">top</a><span class="tocsettoggle"> <a href="javascript:void(0);" title="show/hide table of contents" onclick="TocsetToggle();">contents</a></span></span><span class="navright"> <a href="contract-boundaries.html" title="backward to "7.1 Contracts and Boundaries"" data-pltdoc="x">← prev</a> <a href="contracts.html" title="up to "7 Contracts"" data-pltdoc="x">up</a> <a href="contracts-general-functions.html" title="forward to "7.3 Contracts on Functions in General"" data-pltdoc="x">next →</a></span> </div></div></div><div id="contextindicator"> </div></body></html> |