-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreference.html
More file actions
51 lines (50 loc) · 266 KB
/
reference.html
File metadata and controls
51 lines (50 loc) · 266 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<!DOCTYPE html>
<html>
<head>
<title>L.B.Stanza</title>
<link type="text/css" rel="stylesheet" href="resources/mainstyle.css">
<link type="text/css" rel="stylesheet" href="resources/documentation.css">
</head>
<body>
<table class="wrap">
<tr><td colspan="3" class="banner">
<a href="index.html">Home</a><a href="philosophy.html">Philosophy</a><a href="downloads.html">Downloads</a><a href="documentation.html">Documentation</a><a href="people.html">People</a><a href="community.html">Community</a><a href="news.html">News</a><a href="reference.html" class="active-banner">Reference</a>
</td></tr>
<tr>
<td class="nav">
<h1>NAVIGATION</h1>
<h2><a href="#anchor155">Core Macros</a></h2><h3><a href="#anchor156">Types</a></h3><h4><a href="#anchor157">Function Type</a></h4><h4><a href="#anchor158">Intersection Type</a></h4><h4><a href="#anchor159">Union Type</a></h4><h4><a href="#anchor160">Captured Type Argument</a></h4><h4><a href="#anchor161">Tuple Type</a></h4><h4><a href="#anchor162">Parametric Type</a></h4><h4><a href="#anchor163">Unknown Type</a></h4><h4><a href="#anchor164">Void Type</a></h4><h3><a href="#anchor165">Declarations</a></h3><h4><a href="#anchor166">Package Declarations</a></h4><h4><a href="#anchor167">Public Visibility</a></h4><h4><a href="#anchor168">Protected Visibility</a></h4><h4><a href="#anchor169">Type Declarations</a></h4><h4><a href="#anchor170">Struct Declarations</a></h4><h4><a href="#anchor171">Function Declarations</a></h4><h4><a href="#anchor172">Keyword Arguments</a></h4><h4><a href="#anchor173">Optional Arguments</a></h4><h4><a href="#anchor174">Variadic Arguments</a></h4><h4><a href="#anchor175">Multi Declarations</a></h4><h4><a href="#anchor176">Method Declarations</a></h4><h4><a href="#anchor177">Value Declarations</a></h4><h4><a href="#anchor178">Variable Declarations</a></h4><h4><a href="#anchor179">Enum Declarations</a></h4><h3><a href="#anchor180">Expressions</a></h3><h4><a href="#anchor181">Literal S-Expressions</a></h4><h4><a href="#anchor182">Expression Sequences</a></h4><h4><a href="#anchor183">Function Calls</a></h4><h4><a href="#anchor184">Polymorphic Function Calls</a></h4><h4><a href="#anchor185">Calls to Get</a></h4><h4><a href="#anchor186">Calls to Set</a></h4><h4><a href="#anchor187">Anonymous Functions</a></h4><h4><a href="#anchor188">Curried Functions</a></h4><h4><a href="#anchor189">Casts</a></h4><h4><a href="#anchor190">Upcasts</a></h4><h4><a href="#anchor191">Type Checks</a></h4><h4><a href="#anchor192">Tuples</a></h4><h4><a href="#anchor193">Objects</a></h4><h4><a href="#anchor194">Ranges</a></h4><h4><a href="#anchor195">KeyValue Objects</a></h4><h4><a href="#anchor196">Apply Operator</a></h4><h4><a href="#anchor197">Chained Function Operator '$>'</a></h4><h4><a href="#anchor198">If Conditionals</a></h4><h4><a href="#anchor199">When Conditionals</a></h4><h4><a href="#anchor200">Match Conditionals</a></h4><h4><a href="#anchor201">Quick Match</a></h4><h4><a href="#anchor202">Switch Conditionals</a></h4><h4><a href="#anchor203">Let Scopes</a></h4><h4><a href="#anchor204">Where Scopes</a></h4><h4><a href="#anchor205">For "Loops"</a></h4><h4><a href="#anchor206">Within Blocks</a></h4><h4><a href="#anchor207">While Loops</a></h4><h4><a href="#anchor208">Labeled Scopes</a></h4><h4><a href="#anchor209">Generators</a></h4><h4><a href="#anchor210">Dynamic Variables</a></h4><h4><a href="#anchor211">Exception Handling</a></h4><h4><a href="#anchor212">Attempts and Failures</a></h4><h4><a href="#anchor213">Operators</a></h4><h4><a href="#anchor214">Anonymous Functions</a></h4><h4><a href="#anchor215">Multiple Arity Functions</a></h4><h4><a href="#anchor216">Variable Assignments</a></h4><h4><a href="#anchor217">Quasi Quote</a></h4><h4><a href="#anchor218">Compile Time Flags</a></h4><h3><a href="#anchor219">Build System</a></h3><h4><a href="#anchor220">Simple Project with .stanza Files</a></h4><h4><a href="#anchor221">Creating a stanza.proj File</a></h4><h4><a href="#anchor222">Calling the Compiler</a></h4><h4><a href="#anchor223">Other .proj Files</a></h4><h4><a href="#anchor224">Caching .pkg Files</a></h4><h4><a href="#anchor225">Environment Variables</a></h4><h4><a href="#anchor226">Packages Specified by Directory</a></h4><h4><a href="#anchor227">Special Variables</a></h4><h4><a href="#anchor228">Project Structure</a></h4><h4><a href="#anchor229">Include Statement</a></h4><h4><a href="#anchor230">Foreign File Dependencies</a></h4><h4><a href="#anchor231">Platform-Specific Files and Flags</a></h4><h4><a href="#anchor232">Running a Foreign Compiler</a></h4><h4><a href="#anchor233">Conditional Imports</a></h4><h4><a href="#anchor234">Adding Support for JSON</a></h4><h4><a href="#anchor235">Separating the JSON functionality</a></h4><h4><a href="#anchor236">Automatic Import</a></h4><h4><a href="#anchor237">Build Targets</a></h4><h4><a href="#anchor238">Building Test Targets</a></h4><h2><a href="#anchor239">Core Package</a></h2><h3><a href="#anchor240">Equalable</a></h3><h4><a href="#anchor241">equal?</a></h4><h4><a href="#anchor242">not-equal?</a></h4><h3><a href="#anchor243">Comparable</a></h3><h4><a href="#anchor244">compare</a></h4><h4><a href="#anchor245">less?, greater?, less-eq?, greater-eq?</a></h4><h4><a href="#anchor246">max, min</a></h4><h4><a href="#anchor247">maximum, minimum</a></h4><h3><a href="#anchor248">Hashable</a></h3><h4><a href="#anchor249">hash</a></h4><h3><a href="#anchor250">Lengthable</a></h3><h4><a href="#anchor251">length</a></h4><h3><a href="#anchor252">Seq</a></h3><h4><a href="#anchor253">empty?</a></h4><h4><a href="#anchor254">next</a></h4><h3><a href="#anchor255">PeekSeq</a></h3><h4><a href="#anchor256">peek</a></h4><h3><a href="#anchor257">Seqable</a></h3><h4><a href="#anchor258">to-seq</a></h4><h3><a href="#anchor259">Collection</a></h3><h3><a href="#anchor260">IndexedCollection</a></h3><h4><a href="#anchor261">get, set</a></h4><h4><a href="#anchor262">get</a></h4><h4><a href="#anchor263">set</a></h4><h4><a href="#anchor264">map!</a></h4><h4><a href="#anchor265">empty?</a></h4><h4><a href="#anchor266">reverse!</a></h4><h4><a href="#anchor267">in-reverse</a></h4><h3><a href="#anchor268">OutputStream</a></h3><h4><a href="#anchor269">print</a></h4><h4><a href="#anchor270">print-all</a></h4><h4><a href="#anchor271">println</a></h4><h4><a href="#anchor272">println-all</a></h4><h4><a href="#anchor273">STANDARD-OUTPUT-STREAM</a></h4><h4><a href="#anchor274">with-output-stream</a></h4><h4><a href="#anchor275">current-output-stream</a></h4><h4><a href="#anchor276">print to current OutputStream</a></h4><h4><a href="#anchor277">Standard Error</a></h4><h3><a href="#anchor278">InputStream</a></h3><h4><a href="#anchor279">get-char</a></h4><h4><a href="#anchor280">get-byte</a></h4><h4><a href="#anchor281">STANDARD-INPUT-STREAM</a></h4><h4><a href="#anchor282">fill</a></h4><h3><a href="#anchor283">IndentedStream</a></h3><h4><a href="#anchor284">IndentedStream</a></h4><h4><a href="#anchor285">do-indented</a></h4><h4><a href="#anchor286">indented</a></h4><h3><a href="#anchor287">FileOutputStream</a></h3><h4><a href="#anchor288">FileOutputStream</a></h4><h4><a href="#anchor289">put</a></h4><h4><a href="#anchor290">close</a></h4><h4><a href="#anchor291">with-output-file</a></h4><h4><a href="#anchor292">spit</a></h4><h3><a href="#anchor293">Pretty Printing</a></h3><h4><a href="#anchor294">write</a></h4><h4><a href="#anchor295">write-all</a></h4><h3><a href="#anchor296">FileInputStream</a></h3><h4><a href="#anchor297">FileInputStream</a></h4><h4><a href="#anchor298">close</a></h4><h4><a href="#anchor299">Reading Values</a></h4><h4><a href="#anchor300">slurp</a></h4><h3><a href="#anchor301">StringInputStream</a></h3><h4><a href="#anchor302">StringInputStream</a></h4><h4><a href="#anchor303">peek?</a></h4><h4><a href="#anchor304">info</a></h4><h3><a href="#anchor305">RandomAccessFile</a></h3><h4><a href="#anchor306">RandomAccessFile</a></h4><h4><a href="#anchor307">close</a></h4><h4><a href="#anchor308">writable?</a></h4><h4><a href="#anchor309">length</a></h4><h4><a href="#anchor310">set-length</a></h4><h4><a href="#anchor311">seek</a></h4><h4><a href="#anchor312">skip</a></h4><h4><a href="#anchor313">Reading Values</a></h4><h4><a href="#anchor314">Writing Values</a></h4><h4><a href="#anchor315">Reading Blocks</a></h4><h4><a href="#anchor316">Writing Blocks</a></h4><h3><a href="#anchor317">Numbers</a></h3><h4><a href="#anchor318">Numeric Literals</a></h4><h4><a href="#anchor319">Integer Arithmetic</a></h4><h4><a href="#anchor320">Floating Point Arithmetic</a></h4><h4><a href="#anchor321">Signed Arithmetic</a></h4><h4><a href="#anchor322">Bitwise Operations</a></h4><h4><a href="#anchor323">Numerical Limits</a></h4><h4><a href="#anchor324">Numerical Conversion</a></h4><h4><a href="#anchor325">bits</a></h4><h4><a href="#anchor326">bits-as-float, bits-as-double</a></h4><h4><a href="#anchor327">rand</a></h4><h4><a href="#anchor328">ceil-log2</a></h4><h4><a href="#anchor329">floor-log2</a></h4><h4><a href="#anchor330">next-pow2</a></h4><h4><a href="#anchor331">prev-pow2</a></h4><h4><a href="#anchor332">sum</a></h4><h4><a href="#anchor333">product</a></h4><h3><a href="#anchor334">Boolean Types</a></h3><h4><a href="#anchor335">complement</a></h4><h3><a href="#anchor336">Character Type</a></h3><h4><a href="#anchor337">digit?</a></h4><h4><a href="#anchor338">letter?</a></h4><h4><a href="#anchor339">upper-case?</a></h4><h4><a href="#anchor340">lower-case?</a></h4><h4><a href="#anchor341">lower-case</a></h4><h4><a href="#anchor342">upper-case</a></h4><h3><a href="#anchor343">Range</a></h3><h4><a href="#anchor344">Range</a></h4><h4><a href="#anchor345">Dense Index Ranges</a></h4><h4><a href="#anchor346">start</a></h4><h4><a href="#anchor347">end</a></h4><h4><a href="#anchor348">step</a></h4><h4><a href="#anchor349">inclusive?</a></h4><h4><a href="#anchor350">map</a></h4><h3><a href="#anchor351">String</a></h3><h4><a href="#anchor352">String</a></h4><h4><a href="#anchor353">get</a></h4><h4><a href="#anchor354">get</a></h4><h4><a href="#anchor355">Parsing Numbers</a></h4><h4><a href="#anchor356">to-string</a></h4><h4><a href="#anchor357">String Interpolation</a></h4><h4><a href="#anchor358">matches?</a></h4><h4><a href="#anchor359">prefix?</a></h4><h4><a href="#anchor360">suffix?</a></h4><h4><a href="#anchor361">empty?</a></h4><h4><a href="#anchor362">append</a></h4><h4><a href="#anchor363">append-all</a></h4><h4><a href="#anchor364">string-join</a></h4><h4><a href="#anchor365">index-of-char</a></h4><h4><a href="#anchor366">index-of-chars</a></h4><h4><a href="#anchor367">last-index-of-char</a></h4><h4><a href="#anchor368">last-index-of-chars</a></h4><h4><a href="#anchor369">replace</a></h4><h4><a href="#anchor370">replace</a></h4><h4><a href="#anchor371">split</a></h4><h4><a href="#anchor372">lower-case</a></h4><h4><a href="#anchor373">upper-case</a></h4><h4><a href="#anchor374">trim</a></h4><h3><a href="#anchor375">StringBuffer</a></h3><h4><a href="#anchor376">StringBuffer</a></h4><h4><a href="#anchor377">add</a></h4><h4><a href="#anchor378">add-all</a></h4><h4><a href="#anchor379">clear</a></h4><h3><a href="#anchor380">Array</a></h3><h4><a href="#anchor381">Array</a></h4><h4><a href="#anchor382">to-array</a></h4><h4><a href="#anchor383">map</a></h4><h3><a href="#anchor384">CharArray</a></h3><h4><a href="#anchor385">CharArray</a></h4><h4><a href="#anchor386">get-chars</a></h4><h4><a href="#anchor387">set-chars</a></h4><h3><a href="#anchor388">ByteArray</a></h3><h4><a href="#anchor389">ByteArray</a></h4><h3><a href="#anchor390">Tuple</a></h3><h4><a href="#anchor391">Tuple</a></h4><h4><a href="#anchor392">to-tuple</a></h4><h4><a href="#anchor393">get</a></h4><h4><a href="#anchor394">get</a></h4><h4><a href="#anchor395">map</a></h4><h4><a href="#anchor396">empty?</a></h4><h3><a href="#anchor397">List</a></h3><h4><a href="#anchor398">List</a></h4><h4><a href="#anchor399">cons</a></h4><h4><a href="#anchor400">to-list</a></h4><h4><a href="#anchor401">head</a></h4><h4><a href="#anchor402">tail</a></h4><h4><a href="#anchor403">empty?</a></h4><h4><a href="#anchor404">get</a></h4><h4><a href="#anchor405">headn</a></h4><h4><a href="#anchor406">tailn</a></h4><h4><a href="#anchor407">reverse</a></h4><h4><a href="#anchor408">in-reverse</a></h4><h4><a href="#anchor409">last</a></h4><h4><a href="#anchor410">but-last</a></h4><h4><a href="#anchor411">append</a></h4><h4><a href="#anchor412">append-all</a></h4><h4><a href="#anchor413">transpose</a></h4><h4><a href="#anchor414">map</a></h4><h4><a href="#anchor415">map</a></h4><h4><a href="#anchor416">seq-append</a></h4><h4><a href="#anchor417">seq-append</a></h4><h3><a href="#anchor418">FileInfo</a></h3><h4><a href="#anchor419">FileInfo</a></h4><h4><a href="#anchor420">filename</a></h4><h4><a href="#anchor421">line</a></h4><h4><a href="#anchor422">column</a></h4><h3><a href="#anchor423">Token</a></h3><h4><a href="#anchor424">Token</a></h4><h4><a href="#anchor425">item</a></h4><h4><a href="#anchor426">info</a></h4><h4><a href="#anchor427">unwrap-token</a></h4><h4><a href="#anchor428">unwrap-all</a></h4><h3><a href="#anchor429">KeyValue</a></h3><h4><a href="#anchor430">KeyValue</a></h4><h4><a href="#anchor431">key</a></h4><h4><a href="#anchor432">value</a></h4><h3><a href="#anchor433">Symbols</a></h3><h4><a href="#anchor434">to-symbol</a></h4><h4><a href="#anchor435">symbol-join</a></h4><h4><a href="#anchor436">gensym</a></h4><h4><a href="#anchor437">name</a></h4><h4><a href="#anchor438">id</a></h4><h4><a href="#anchor439">qualified?</a></h4><h4><a href="#anchor440">qualifier</a></h4><h4><a href="#anchor441">String Representation</a></h4><h3><a href="#anchor442">Maybe</a></h3><h4><a href="#anchor443">One</a></h4><h4><a href="#anchor444">None</a></h4><h4><a href="#anchor445">value</a></h4><h4><a href="#anchor446">value?</a></h4><h4><a href="#anchor447">value!</a></h4><h4><a href="#anchor448">empty?</a></h4><h3><a href="#anchor449">Exception</a></h3><h4><a href="#anchor450">Exception</a></h4><h4><a href="#anchor451">throw</a></h4><h4><a href="#anchor452">with-exception-handler</a></h4><h4><a href="#anchor453">with-finally</a></h4><h4><a href="#anchor454">try-catch-finally</a></h4><h3><a href="#anchor455">Fatal Errors</a></h3><h4><a href="#anchor456">fatal</a></h4><h3><a href="#anchor457">Attempt and Failure</a></h3><h4><a href="#anchor458">fail</a></h4><h4><a href="#anchor459">with-attempt</a></h4><h4><a href="#anchor460">attempt-else</a></h4><h3><a href="#anchor461">Labeled Scopes</a></h3><h4><a href="#anchor462">LabeledScope</a></h4><h4><a href="#anchor463">label</a></h4><h3><a href="#anchor464">Generators</a></h3><h4><a href="#anchor465">Generator</a></h4><h4><a href="#anchor466">generate</a></h4><h3><a href="#anchor467">Coroutine</a></h3><h4><a href="#anchor468">Coroutine</a></h4><h4><a href="#anchor469">resume</a></h4><h4><a href="#anchor470">suspend</a></h4><h4><a href="#anchor471">break</a></h4><h4><a href="#anchor472">close</a></h4><h4><a href="#anchor473">active?</a></h4><h4><a href="#anchor474">open?</a></h4><h3><a href="#anchor475">Dynamic Wind</a></h3><h4><a href="#anchor476">dynamic-wind</a></h4><h3><a href="#anchor477">Sequence Library</a></h3><h4><a href="#anchor478">Operating Functions</a></h4><h4><a href="#anchor479">do</a></h4><h4><a href="#anchor480">find</a></h4><h4><a href="#anchor481">find!</a></h4><h4><a href="#anchor482">first</a></h4><h4><a href="#anchor483">first!</a></h4><h4><a href="#anchor484">seq</a></h4><h4><a href="#anchor485">seq?</a></h4><h4><a href="#anchor486">filter</a></h4><h4><a href="#anchor487">index-when</a></h4><h4><a href="#anchor488">index-when!</a></h4><h4><a href="#anchor489">split!</a></h4><h4><a href="#anchor490">split</a></h4><h4><a href="#anchor491">fork</a></h4><h4><a href="#anchor492">take-while</a></h4><h4><a href="#anchor493">take-until</a></h4><h4><a href="#anchor494">seq-cat</a></h4><h4><a href="#anchor495">all?</a></h4><h4><a href="#anchor496">none?</a></h4><h4><a href="#anchor497">any?</a></h4><h4><a href="#anchor498">count</a></h4><h4><a href="#anchor499">Sequence Constructors</a></h4><h4><a href="#anchor500">repeat</a></h4><h4><a href="#anchor501">repeatedly</a></h4><h4><a href="#anchor502">repeat-while</a></h4><h4><a href="#anchor503">Sequence Operators</a></h4><h4><a href="#anchor504">filter</a></h4><h4><a href="#anchor505">take-n</a></h4><h4><a href="#anchor506">take-up-to-n</a></h4><h4><a href="#anchor507">cat</a></h4><h4><a href="#anchor508">cat-all</a></h4><h4><a href="#anchor509">join</a></h4><h4><a href="#anchor510">zip</a></h4><h4><a href="#anchor511">zip-all</a></h4><h4><a href="#anchor512">Sequence Reducers</a></h4><h4><a href="#anchor513">contains?</a></h4><h4><a href="#anchor514">index-of</a></h4><h4><a href="#anchor515">index-of!</a></h4><h4><a href="#anchor516">split</a></h4><h4><a href="#anchor517">count</a></h4><h4><a href="#anchor518">reduce</a></h4><h4><a href="#anchor519">reduce-right</a></h4><h4><a href="#anchor520">unique</a></h4><h4><a href="#anchor521">lookup?</a></h4><h4><a href="#anchor522">lookup</a></h4><h4><a href="#anchor523">fork-on-seq</a></h4><h3><a href="#anchor524">Sorting</a></h3><h4><a href="#anchor525">qsort!</a></h4><h4><a href="#anchor526">lazy-qsort</a></h4><h3><a href="#anchor527">LivenessTracker</a></h3><h4><a href="#anchor528">LivenessTracker</a></h4><h4><a href="#anchor529">value</a></h4><h4><a href="#anchor530">marker</a></h4><h4><a href="#anchor531">marker!</a></h4><h4><a href="#anchor532">add-gc-notifier</a></h4><h3><a href="#anchor533">Files & Directories</a></h3><h4><a href="#anchor534">file-exists?</a></h4><h4><a href="#anchor535">file-type</a></h4><h4><a href="#anchor536">rename-file</a></h4><h4><a href="#anchor537">copy-file</a></h4><h4><a href="#anchor538">symlink</a></h4><h4><a href="#anchor539">delete-file</a></h4><h4><a href="#anchor540">delete-recursive</a></h4><h4><a href="#anchor541">resolve-path</a></h4><h4><a href="#anchor542">split-filepath</a></h4><h4><a href="#anchor543">dir-files</a></h4><h4><a href="#anchor544">create-dir</a></h4><h4><a href="#anchor545">create-dir-recursive</a></h4><h3><a href="#anchor546">System Utilities</a></h3><h4><a href="#anchor547">command-line-arguments</a></h4><h4><a href="#anchor548">current-time-ms</a></h4><h4><a href="#anchor549">current-time-us</a></h4><h4><a href="#anchor550">get-env</a></h4><h4><a href="#anchor551">set-env</a></h4><h4><a href="#anchor552">unset-env</a></h4><h4><a href="#anchor553">call-system</a></h4><h4><a href="#anchor554">call-system-and-get-output</a></h4><h4><a href="#anchor555">replace-current-process</a></h4><h4><a href="#anchor556">exit</a></h4><h3><a href="#anchor557">Timer</a></h3><h4><a href="#anchor558">MillisecondTimer</a></h4><h4><a href="#anchor559">MicrosecondTimer</a></h4><h4><a href="#anchor560">PiggybackTimer</a></h4><h4><a href="#anchor561">start</a></h4><h4><a href="#anchor562">stop</a></h4><h4><a href="#anchor563">time</a></h4><h2><a href="#anchor564">Math Package</a></h2><h3><a href="#anchor565">Quantities</a></h3><h4><a href="#anchor566">PI</a></h4><h4><a href="#anchor567">PI-F</a></h4><h3><a href="#anchor568">Basic Operations</a></h3><h4><a href="#anchor569">exp</a></h4><h4><a href="#anchor570">log</a></h4><h4><a href="#anchor571">log10</a></h4><h4><a href="#anchor572">pow</a></h4><h4><a href="#anchor573">sin</a></h4><h4><a href="#anchor574">cos</a></h4><h4><a href="#anchor575">tan</a></h4><h4><a href="#anchor576">asin</a></h4><h4><a href="#anchor577">acos</a></h4><h4><a href="#anchor578">atan</a></h4><h4><a href="#anchor579">atan2</a></h4><h4><a href="#anchor580">sinh</a></h4><h4><a href="#anchor581">cosh</a></h4><h4><a href="#anchor582">tanh</a></h4><h4><a href="#anchor583">ceil</a></h4><h4><a href="#anchor584">floor</a></h4><h4><a href="#anchor585">round</a></h4><h4><a href="#anchor586">to-radians</a></h4><h4><a href="#anchor587">to-degrees</a></h4><h2><a href="#anchor588">Collections Package</a></h2><h3><a href="#anchor589">Vector</a></h3><h4><a href="#anchor590">Vector</a></h4><h4><a href="#anchor591">to-vector</a></h4><h4><a href="#anchor592">add</a></h4><h4><a href="#anchor593">add-all</a></h4><h4><a href="#anchor594">clear</a></h4><h4><a href="#anchor595">pop</a></h4><h4><a href="#anchor596">peek</a></h4><h4><a href="#anchor597">remove</a></h4><h4><a href="#anchor598">remove</a></h4><h4><a href="#anchor599">update</a></h4><h4><a href="#anchor600">remove-item</a></h4><h4><a href="#anchor601">remove-when</a></h4><h4><a href="#anchor602">trim</a></h4><h4><a href="#anchor603">shorten</a></h4><h4><a href="#anchor604">lengthen</a></h4><h4><a href="#anchor605">set-length</a></h4><h4><a href="#anchor606">map</a></h4><h3><a href="#anchor607">Queue</a></h3><h4><a href="#anchor608">Queue</a></h4><h4><a href="#anchor609">add</a></h4><h4><a href="#anchor610">pop</a></h4><h4><a href="#anchor611">peek</a></h4><h4><a href="#anchor612">clear</a></h4><h3><a href="#anchor613">Set</a></h3><h4><a href="#anchor614">add</a></h4><h4><a href="#anchor615">remove</a></h4><h4><a href="#anchor616">get</a></h4><h4><a href="#anchor617">clear</a></h4><h3><a href="#anchor618">Table</a></h3><h4><a href="#anchor619">set</a></h4><h4><a href="#anchor620">get?</a></h4><h4><a href="#anchor621">default?</a></h4><h4><a href="#anchor622">remove</a></h4><h4><a href="#anchor623">clear</a></h4><h4><a href="#anchor624">get?</a></h4><h4><a href="#anchor625">get</a></h4><h4><a href="#anchor626">key?</a></h4><h4><a href="#anchor627">keys</a></h4><h4><a href="#anchor628">values</a></h4><h4><a href="#anchor629">empty?</a></h4><h3><a href="#anchor630">HashTable</a></h3><h4><a href="#anchor631">HashTable</a></h4><h2><a href="#anchor632">Reader Package</a></h2><h4><a href="#anchor633">read-file</a></h4><h4><a href="#anchor634">read-all</a></h4><h4><a href="#anchor635">read-all</a></h4><h4><a href="#anchor636">read</a></h4><h2><a href="#anchor637">Macro Utilities Package</a></h2><h3><a href="#anchor638">Utility Functions</a></h3><h4><a href="#anchor639">tagged-list?</a></h4><h3><a href="#anchor640">S-Expression Template Engine</a></h3><h4><a href="#anchor641">fill-template</a></h4><h4><a href="#anchor642">Simple Replacements</a></h4><h4><a href="#anchor643">Splice Template</a></h4><h4><a href="#anchor644">Nested Template</a></h4><h4><a href="#anchor645">Plural Template</a></h4><h4><a href="#anchor646">Choice Template</a></h4>
</td>
<td class="main">
<h1 id="anchor155">Core Macros</h1><p>The core macros are the default macros used for expanding s-expressions into Stanza core forms.</p><h2 id="anchor156">Types</h2><p></p><h3 id="anchor157">Function Type</h3><p>A function type is specified using the <code>-></code> operator. The arguments to the function are to the left-hand side of the <code>-></code>, and the return type of the function is on the right-hand side of the <code>-></code>.</p><pre><code>(Int, Int) -> Int</code></pre><p>If there is exactly a single argument, then the parentheses surrounding the argument types may be omitted.</p><pre><code>Int -> Int</code></pre><h3 id="anchor158">Intersection Type</h3><p>An intersection type is specified using the <code>&</code> operator.</p><pre><code>Seqable & Lengthable</code></pre><h3 id="anchor159">Union Type</h3><p>A union type is specified using the <code>|</code> operator.</p><pre><code>Int | String</code></pre><h3 id="anchor160">Captured Type Argument</h3><p>A captured type argument is specified by prefixing an identifier with the <code>?</code> operator.</p><pre><code>?T</code></pre><h3 id="anchor161">Tuple Type</h3><p>A tuple type is specified by surrounding a sequence of types between the <code>[]</code> brackets.</p><pre><code>[Int, String]</code></pre><h3 id="anchor162">Parametric Type</h3><p>A parametric type is specified by following an identifier with a sequence of types between the <code><></code> brackets.</p><pre><code>Table<Int, String></code></pre><h3 id="anchor163">Unknown Type</h3><p>The special identifier <code>?</code> represents the unknown type.</p><pre><code>?</code></pre><h3 id="anchor164">Void Type</h3><p>The special identifer <code>Void</code> represents the void type.</p><pre><code>Void</code></pre><h2 id="anchor165">Declarations</h2><p></p><h3 id="anchor166">Package Declarations</h3><p>The following form declares a new package with no imported packages.</p><pre><code>defpackage mypackage</code></pre><p>Bindings from other packages may be imported using the <code>import</code> statement.</p><pre><code>defpackage mypackage :<br> import core<br> import collections</code></pre><p>Prefixes may be added to bindings from an imported package. The following form will append the prefix <code>core-</code> to every imported binding from the <code>core</code> package, except for bindings named <code>False</code>, which will instead have the <code>C</code> prefix.</p><pre><code>defpackage mypackage :<br> import core with :<br> prefix => core-<br> prefix(False) => C</code></pre><p>In addition to the <code>import</code> statement, there is also the <code>forward</code> statement:</p><pre><code>defpackage mypackage :<br> import core<br> forward mydefs</code></pre><p>The <code>forward</code> statement will import the package <code>mydefs</code> and then expose any <code>public</code> symbols found in it as if they are coming from the <code>mypackage</code> package.</p><h3 id="anchor167">Public Visibility</h3><p>Either of the following forms can be used to indicate that the following declaration(s) is/are publicly visible.</p><pre><code>public decl<br>public : decl</code></pre><p>The colon version is typically used to indicate the visibility of multiple declarations.</p><pre><code>public :<br> val x = 10<br> val y = 20</code></pre><h3 id="anchor168">Protected Visibility</h3><p>Either of the following forms can be used to indicate that the following declaration(s) has/have protected visibility. This indicates that they can only be referenced from other packages through package-qualified identifiers.</p><pre><code>protected decl<br>protected : decl</code></pre><h3 id="anchor169">Type Declarations</h3><p>The following form defines the type <code>MyType</code>.</p><pre><code>deftype MyType</code></pre><p>The following form defines the type <code>MyType</code> as a subtype of <code>Collection</code> and <code>Lengthable</code>.</p><pre><code>deftype MyType <: Collection & Lengthable</code></pre><p>The following form defines the type <code>MyType</code>, and also defines the types <code>Int</code> and <code>String</code> to be subtypes of <code>MyType</code>.</p><pre><code>deftype MyType :<br> Int <: MyType<br> String <: MyType</code></pre><p>Parametric types may be defined as follows.</p><pre><code>deftype MyType<T></code></pre><p>These type parameters may be used in the specification of the types parents.</p><pre><code>deftype MyType<T> <: Collection<T> & Lengthable</code></pre><h3 id="anchor170">Struct Declarations</h3><p>The following form defines the struct <code>MyStruct</code> with the given fields <code>x</code> of type <code>XType</code> and <code>y</code> of type <code>YType</code>.</p><pre><code>defstruct MyStruct :<br> x: XType<br> y: YType</code></pre><p>The above form will expand into:</p><ol><li>a type declaration for the type <code>MyStruct</code>.
</li><li>a constructor function called <code>MyStruct</code> that takes in two arguments, an <code>XType</code> and a <code>YType</code> object and returns a <code>MyStruct</code> object.
</li><li>two getter functions named <code>x</code> and <code>y</code> that return the associated field in the struct.
</li></ol><p>To change the name of the generated constructor function, the following option may be used.</p><pre><code>defstruct MyStruct :<br> x: XType<br> y: YType<br>with :<br> constructor => #MyStruct</code></pre><p>The generated constructor function will now be named <code>#MyStruct</code> instead of <code>MyStruct</code> with the above form.</p><p>To generate a default implementation of a printer, set the <code>printer</code> option to <code>true</code>.</p><pre><code>defstruct Person :<br> name: String<br> age: Int<br>with:<br> printer => true </code></pre><p>The generated printer is meant for debugging purposes only and quickly generates a string representation of a simple structure. You should provide your own custom printer if this is not the case.</p><p>The parent type of a struct may be provided using the following form.</p><pre><code>defstruct MyStruct <: Parent :<br> x: XType<br> y: YType</code></pre><p>To create a parametrically typed struct, type arguments can be given following the type name.</p><pre><code>defstruct MyStruct<T> :<br> x: XType<br> y: YType<br> z: Array<T></code></pre><p>Mutable fields may be declared by providing the name of a setter function. In the following example, a setter function called <code>set-x</code> will be generated for setting the value of the <code>x</code> field.</p><pre><code>defstruct MyStruct :<br> x: XType with: (setter => set-x)<br> y: YType</code></pre><p>The generated <code>set-x</code> function has the following type signature.</p><pre><code>defn set-x (s:MyStruct, x:XType) -> False</code></pre><p>To generate field accessors as methods instead of as functions, the following form may be used.</p><pre><code>defstruct MyStruct :<br> x: XType with: (as-method => true)</code></pre><p>The above example will generate the <code>x</code> getter as a method instead of a function.</p><pre><code>defmethod set-x (s:MyStruct, x:XType) -> False</code></pre><p>Similar to setters, "updaters" can be defined using the <code>updater</code> option. In the following example, the <code>x</code> and <code>y</code> fields can be "updated" with new values.</p><pre><code>defstruct Point :<br> x:Int with: (updater => sub-x)<br> y:Int with: (updater => sub-y)</code></pre><p>An updater takes an initial <code>Point</code> object and creates a new <code>Point</code> object by substituting the given value. In the following example the point <code>p1</code> represents <code>(1,2)</code>, <code>p2</code> represents <code>(3,2)</code>, and <code>p3</code> represents <code>(1,4)</code>. Updaters are used frequently when programming with immutable datastructures.</p><pre><code>val p1 = Point(1,2)<br>val p2 = sub-x(p1, 3)<br>val p3 = sub-y(p1, 4)</code></pre><p>To provide default values for field values, the <code>default</code> option can be used. In the following example, the <code>x</code> and <code>y</code> fields will have a default value of 0, if no value is provided.</p><pre><code>defstruct Point :<br> x:Int with: (default => 0)<br> y:Int with: (default => 0)</code></pre><p>With the above definition, the user can create a point like this</p><pre><code>val origin = Point()</code></pre><p>Often for mutable structures, we always want a certain field to be initialized to some value. The following example creates a struct called <code>Person</code>, whose age is always initialized to zero. </p><pre><code>defstruct Person :<br> name:String<br> age:Int with: (init => 0, setter => set-age)</code></pre><p>A <code>Person</code> object can be created like this</p><pre><code>val p = Person("Patrick")<br>set-age(p, 23)</code></pre><p>The <code>default</code> and <code>init</code> options allow for a special value called <code>void</code> that allows these fields to remain uninitialized. Here is a <code>Person</code> struct whose age is uninitialized when first created.</p><pre><code>defstruct Person :<br> name:String<br> age:Int with: (init => void, setter => set-age)</code></pre><p>Note that it is an error to read from a field that has not yet been initialized.</p><p>The <code>ensure</code> option is used to prevent objects from being created with invalid arguments. It takes a precondition checking function that is meant to call <code>fatal</code> if the given arguments do not satisfy the intended preconditions. The following example shows a <code>Point</code> object whose fields are restricted to be strictly positive. </p><pre><code>defstruct Point :<br> x:Int with: (ensure => positive!)<br> y:Int with: (ensure => positive!)<br><br>defn positive! (field-name:String, value:Int) :<br> if value <= 0 :<br> fatal("Value %_ given to %_ is not positive." % [value, field-name])</code></pre><p>The checking function passed to <code>ensure</code> will be provided two arguments: a <code>String</code> containing the name of the field, and the argument passed to the constructor.</p><h3 id="anchor171">Function Declarations</h3><p>Argument lists have the following form:</p><pre><code>(x:Int, y:Int, z)</code></pre><p>Each argument binding consists of a binding expression (typically an identifier) followed by a colon and an optional type for the argument.</p><p>Tuples (and nested tuples) may be used for binding expressions in order to deconstruct an argument's value.</p><pre><code>([x, y]:[Int, String], y:Int, z)</code></pre><p>The following form defines the named function <code>f</code>.</p><pre><code>defn f (x, y) :<br> x + y</code></pre><p>If no explicit type is given for an argument to a named function, then by default it is assigned the unknown type.</p><p>Users may optionally declare the types of the arguments and the return value using the following form.</p><pre><code>defn f (x:Int, y:String) -> Char :<br> x + y</code></pre><p>To declare tail-recursive functions use the <code>defn*</code> tag in place of the <code>defn</code> tag in the above forms.</p><h3 id="anchor172">Keyword Arguments</h3><p>Argument bindings can use keyword named arguments by using the following syntax:</p><pre><code>defn f (a:Int -- b:String) :<br> println("A: %_ B: %_" % [a, b])</code></pre><p>Note the <code>--</code> as a separator between the positional arguments and the keyword arguments. In this example - <code>a</code> is a positional argument and <code>b</code> is a "Keyword Argument". The function <code>f</code> can be invoked in the following ways:</p><pre><code>stanza> f(10, b = "Hello")<br>A: 10 B: Hello<br>false<br>stanza> f(b = "Hello", 10)<br>A: 10 B: Hello<br>false</code></pre><p>Invoking <code>f</code> without the named keyword <code>b</code> (ie, treating <code>b</code> as just another positional argument) is not allowed:</p><pre><code>stanza> f(10, "Hello")<br>No appropriate function 'f' for argument types (Int, String). Possibilities are:<br> f: (Int, b:String) -> False in package 'repl16966'</code></pre><h3 id="anchor173">Optional Arguments</h3><p>Both positional arguments and keyword arguments can be made optional by supplying any expression as the default value for that argument. Example:</p><pre><code>defn g (a:Int = 10 -- b:String = "Goodbye") :<br> println("A: %_ B: %_" % [a, b])</code></pre><p>In this construction all of the following are valid:</p><pre><code>stanza> g(b = "Hell0")<br>A: 10 B: Hell0<br>false<br>stanza> g(5)<br>A: 5 B: Goodbye<br>false<br>stanza> g()<br>A: 10 B: Goodbye<br>stanza> g(15, b = "Back Again")<br>A: 15 B: Back Again<br>false<br>stanza> g(b = "Back Again", 25)<br>A: 25 B: Back Again<br>false</code></pre><p>Using <code>b</code> as a positional argument will cause a syntax error as before.</p><p>The expression used as the default is not limited to just a string constant. This expression can:</p><p>1. be a function call</p><p>2. reference other arguments by name</p><p>3. have side effects</p><p>4. be unknown at compile time</p><p>The expression must evaluate to the type of the argument that it is applied to.</p><p>This default expression is executed when the function invocation occurs. This is in stark contrast to Python, for example, where the expression for the default value of an argument is executed at creation of the function or class.</p><p>This can help avoid a whole <a href=https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments>class of errors</a> but does come with runtime trade-offs.</p><h3 id="anchor174">Variadic Arguments</h3><p>The following defines a function that takes one integer argument and 0 or more string arguments:</p><pre><code> defn func (a:Int, b:String ...):<br> println("A: %_ len(B): %_ B: %," % [a, length(b), b])</code></pre><p>In the body of <code>func</code>, the argument <code>b</code> will have type <code>Tuple<String></code>. If we invoke this function we see the following:</p><pre><code>stanza> func(10)<br>A: 10 len(B): 0 B: <br>false<br>stanza> func(10, "asdf")<br>A: 10 len(B): 1 B: asdf<br>false<br>stanza> func(10, "asdf", "qwer")<br>A: 10 len(B): 2 B: asdf, qwer<br>false</code></pre><p>We can also pass the argument <code>b</code> by keyword argument:</p><pre><code>stanza> func(10, b = ["apples", "grapes", "bananas"])<br>A: 10 len(B): 3 B: apples, grapes, bananas<br>false</code></pre><h3 id="anchor175">Multi Declarations</h3><p>The following form declares a multi, <code>f</code>, with the given type signature.</p><pre><code>defmulti f (x:Int, y:String) -> String</code></pre><p>If no explicit types are provided for the arguments or return type, then they have the unknown type by default.</p><pre><code>defmulti f (x, y)</code></pre><h3 id="anchor176">Method Declarations</h3><p>The following form declares a method for the multi <code>f</code>.</p><pre><code>defmethod f (x, y) :<br> x + y</code></pre><p>If no explicit types are provided for the arguments then they are assigned the unknown type by default. Users may optionally declare the types of the arguments and the return value using the following form.</p><pre><code>defmethod f (x:Int, y:String) -> Int :<br> x + y</code></pre><p>To declare tail-recursive methods use the <code>defmethod*</code> tag in place of the <code>defmethod</code> tag in the above forms.</p><h3 id="anchor177">Value Declarations</h3><p>The following form declares a value <code>x</code> of type <code>Int</code> initialized to the expression <code>v</code>.</p><pre><code>val x : Int = v</code></pre><p>If the type is omitted then it is inferred from the given value.</p><pre><code>val x = v</code></pre><p>Tuples may be used within the binding expression to destructure the given value.</p><pre><code>val [x, [y, z]] = v</code></pre><h3 id="anchor178">Variable Declarations</h3><p>The following form declares a variable.</p><pre><code>var x : Int = v</code></pre><p>If the type is omitted then it is inferred from any assignments to the variable.</p><pre><code>var x = v</code></pre><p>The initializing expression may be omitted to declare an uninitialized variable. It is an error to read from a variable that is not yet initialized.</p><pre><code>var x</code></pre><h3 id="anchor179">Enum Declarations</h3><p>Enumerated types are defined with the <code>defenum</code> macro:</p><pre><code>defenum Direction :<br> N<br> E<br> S<br> W</code></pre><p>When defining an enum, the macro expands to a <code>deftype</code> for <code>Direction</code> and then separate <code>deftype</code>'s for each of the enumerated values:</p><pre><code>deftype Direction <: Equalable & Hashable<br>deftype N <: Direction<br>deftype E <: Direction<br>deftype S <: Direction<br>deftype W <: Direction</code></pre><p>The macro also expands the following functions for ease of use.</p><pre><code>; Direction -> Int and vice versa<br>defn Direction (i:Int) -> Direction<br>defn Direction? (i:Int) -> Direction|False<br>defn to-int (d:Direction) -> Int<br>; To satisfy Equalable & Hashable<br>defmethod equal? (a:Direction, b:Direction) -> Int<br>defmethod hash (x:Direction) -> Int<br>; Printing<br>defmethod print (o:OutputStream, x:Direction) -> False</code></pre><p>Note that the enumerated integer values are ordered and start from 0. In this case N=0, E=1, S=2, W=3.</p><p>The <code>defenum</code> can also take a parent type just like a <code>deftype</code>:</p><pre><code>public deftype AssetType<br><br>public defenum CompilerOutputs <: AssetType :<br> ObjectFile<br> Executable<br> SharedLibrary</code></pre><h2 id="anchor180">Expressions</h2><p>There are only a handful of core forms in Stanza but the core macro library provides a large collection of syntactic sugar for expressing commonly used constructs.</p><h3 id="anchor181">Literal S-Expressions</h3><p>The backtick form represents a literal s-expression. For example, the following form creates a list consisting of three elements: the symbol f, the integer 3, and the symbol g.</p><pre><code>`(f 3 g)</code></pre><h3 id="anchor182">Expression Sequences</h3><p>Multiple expressions surrounded with parenthesis represent a sequence of expressions, whose value is equal to the value of the last expression.</p><pre><code>(x + 3, 3, f(3))</code></pre><h3 id="anchor183">Function Calls</h3><p>Expressions followed immediately opening parenthesis expand to function call forms.</p><pre><code>f(x)</code></pre><h3 id="anchor184">Polymorphic Function Calls</h3><p>Expressions followed by angle brackets then opening parenthesis expand to polymorphic function call forms.</p><pre><code>f<Int>(x)</code></pre><h3 id="anchor185">Calls to Get</h3><p>Expressions followed by opening square brackets expand to a call to the <code>get</code> function.</p><pre><code>f[x, y]</code></pre><p>expands to</p><pre><code>get(f, x, y)</code></pre><h3 id="anchor186">Calls to Set</h3><p>Expressions followed by opening square brackets and then an equal sign expands to a call to the <code>set</code> function.</p><pre><code>f[x, y] = v</code></pre><p>expands to</p><pre><code>set(f, x, y, v)</code></pre><h3 id="anchor187">Anonymous Functions</h3><p>Expressions wrapped in curly brackets expand to an anonymous function, with underscores replaced by arguments.</p><pre><code>{_ + y}</code></pre><p>expands to</p><pre><code>fn (x) : x + y</code></pre><p>For convenience, if there are no underscores, then the created anonymous function can take both no arguments and a single argument.</p><pre><code>{y}</code></pre><p>expands to</p><pre><code>multifn :<br> () : y<br> (x) : y</code></pre><h3 id="anchor188">Curried Functions</h3><p>Expressions followed by an opening curly bracket expand to an anonymous function, with underscores replaced by arguments.</p><pre><code>f{_, y}</code></pre><p>expands to</p><pre><code>fn (x) : f(x, y)</code></pre><p>If there are no underscores, then the created anonymous function can take both no arguments and a single argument.</p><pre><code>f{y}</code></pre><p>expands to</p><pre><code>multifn :<br> () : f(y)<br> (x) : f(y)</code></pre><h3 id="anchor189">Casts</h3><p>A value can be downcast to a given type using the <code>as</code> operator.</p><pre><code>x as Int</code></pre><p>If followed with an <code>else</code> clause, then the as operator will return the given default value if the expression is not of the given type.</p><pre><code>x as Int else y</code></pre><h3 id="anchor190">Upcasts</h3><p>A value can be upcast to a given type using the <code>as?</code> operator.</p><pre><code>x as? Int</code></pre><h3 id="anchor191">Type Checks</h3><p>The following form returns true if the given value is of the type <code>Type</code> or <code>false</code> otherwise.</p><pre><code>x is Type</code></pre><p>The following form returns true if the given value is not of the type <code>Type</code> or <code>false</code> otherwise.</p><pre><code>x is-not Type</code></pre><h3 id="anchor192">Tuples</h3><p>Tuples are created by surrounding a sequence of expressions with the <code>[]</code> brackets.</p><pre><code>[x, y]</code></pre><h3 id="anchor193">Objects</h3><p>The following form creates a new object of the type <code>MyType</code> with no instance methods.</p><pre><code>new MyType</code></pre><p>The following form creates a new object of the type <code>MyType</code> with instance methods. An instance method follows the same syntax as top-level methods, but requires precisely one argument named <code>this</code> that refers to the object being created.</p><pre><code>new MyType :<br> defmethod f (this, y:Int) :<br> x + y</code></pre><h3 id="anchor194">Ranges</h3><p>The following form creates a <code>Range</code> from <code>a</code> to <code>b</code> (exclusive) with a step size of 1.</p><pre><code>a to b</code></pre><p>A step size may be provided explicit using the <code>by</code> keyword.</p><pre><code>a to b by 2</code></pre><p>To indicate that the ending index should be inclusive rather than exclusive, the <code>through</code> keyword may be used in place of the <code>to</code> keyword.</p><pre><code>a through b<br>a through b by 2</code></pre><h3 id="anchor195">KeyValue Objects</h3><p>The following form creates a <code>KeyValue</code> object from the given key object <code>k</code>, and the value object <code>v</code>.</p><pre><code>k => v</code></pre><h3 id="anchor196">Apply Operator</h3><p>The following operator calls the expression <code>f</code> with the argument <code>x</code>.</p><pre><code>f $ x</code></pre><p>It is often used in conjunction with curried functions to chain together long expressions.</p><pre><code>request-price $<br>{_ * 0.75} $<br>calc-mortgage{_, 75.00} $<br>base-price()</code></pre><h3 id="anchor197">Chained Function Operator '$>'</h3><p>The following operator allows the functions <code>func1</code> and <code>func2</code> to be called in sequence (chained). The input value <code>some-input</code> is passed as the argument to <code>func1</code>. <code>func1</code> is invoked and the output is applied as the argument to <code>func2</code>.</p><pre><code>some-input $> func1 $> func2</code></pre><p>Example:</p><pre><code>stanza> val data = [" what", "a wonderful", "world. "]<br>stanza> val msg = data $> string-join{_, " "} $> trim $> upper-case<br>stanza> println(msg)<br>WHAT A WONDERFUL WORLD.</code></pre><p>Here a tuple of strings is joined, trimmed of white-space, and converted to uppercase letters in a chained sequence of operations.</p><h3 id="anchor198">If Conditionals</h3><p>The following form evaluates one of two branches depending on whether the predicate <code>p</code> is <code>true</code> or <code>false</code>.</p><pre><code>if p :<br> consequent<br>else :<br> alternate</code></pre><p>If the <code>else</code> branch is omitted, then a default <code>else</code> branch is provided that simply returns <code>false</code>.</p><pre><code>if p :<br> consequent</code></pre><p>If the <code>else</code> branch consists of a single <code>if</code> expression, then the colon following the <code>else</code> may be omitted. This allows multiple <code>if</code> expressions to be chained elegantly.</p><pre><code>if p1 :<br> consequent1<br>else if p2 :<br> consequent2<br>else if p3 :<br> consequent3<br>else :<br> alternate</code></pre><h3 id="anchor199">When Conditionals</h3><p>The following form allows for simple branches on <code>true</code>/<code>false</code> to be written concisely.</p><pre><code>consequent when p else alternate</code></pre><p>expands to:</p><pre><code>if p :<br> consequent<br>else :<br> alternate</code></pre><p>If the <code>else</code> clause is omitted, then it returns <code>false</code> by default.</p><h3 id="anchor200">Match Conditionals</h3><p>The following form evaluates one of a multiple of branches depending on the types of its arguments. If no type is given for a branch argument then it is inferred from the type of the input arguments.</p><pre><code>match(x, y) :<br> (x:Int, y:Int) : body0<br> (x:Int, y:String) : body1<br> (x:String, y:Int) : body2<br> (x, y) : body3</code></pre><h3 id="anchor201">Quick Match</h3><p>There is another version of the <code>match</code> statement:</p><pre><code>match(x:Int):<br> x * 2<br>else:<br> throw(Exception("X is not an Int"))</code></pre><p>This provides a condensed syntax for matching against only one type of object and ignoring or raising an error for the rest. In this example, anything that is not an <code>Int</code> throws an exception.</p><h3 id="anchor202">Switch Conditionals</h3><p>The following form creates a chain of <code>if-else</code> expressions for evaluating a sequence of bodies.</p><pre><code>switch f :<br> a : body0<br> b : body1<br> c : body2<br> d : body3<br> else : body4</code></pre><p>expands to:</p><pre><code>if f(a) : body0<br>else if f(b) : body1<br>else if f(c) : body2<br>else if f(d) : body3<br>else : body4</code></pre><p>If no <code>else</code> branch is given, then the default behaviour is to exit the program with a fatal error.</p><p>The <code>switch</code> is commonly used with the <code>equal?</code> predicate function.</p><pre><code>switch {x == _} :<br> 1 : first-action()<br> 2 : second-action()<br> 3 : third-action()</code></pre><h3 id="anchor203">Let Scopes</h3><p>The following form evaluates its body under a new scope.</p><pre><code>let :<br> body</code></pre><h3 id="anchor204">Where Scopes</h3><p>The following form evaluates an expression with a set of declared bindings.</p><pre><code>exp where :<br> body</code></pre><p>expands to:</p><pre><code>let :<br> body<br> exp</code></pre><p>The following example demonstrates assigning to <code>x</code> the result of <code>42 - (10 * y)</code>.</p><pre><code>x = (42 - z) where :<br> val z = 10 * y</code></pre><h3 id="anchor205">For "Loops"</h3><p>The following form calls an operating function, <code>f</code>, with an anonymous function and a list of arguments.</p><pre><code>for (x in xs, y in ys, z in zs) f :<br> body</code></pre><p>expands to:</p><pre><code>f((fn (x, y, z) : body), xs, ys, zs)</code></pre><p>If there is only a single set of bindings, then the parenthesis may be omitted.</p><pre><code>for x in xs f :<br> body</code></pre><p>By far, the most common usage of the <code>for</code> construct is with the <code>do</code> function to iterate over sequences. The following example prints the integers between <code>0</code> and <code>10</code>.</p><pre><code>for i in 0 to 10 do :<br> println(i)</code></pre><h3 id="anchor206">Within Blocks</h3><p>The following form</p><pre><code>within result = f(x, y, z) :<br> body</code></pre><p>expands into a call to <code>f</code> with an additional function representing the block body.</p><p>The above is equivalent to this:</p><pre><code>f(<br> fn (result) : body,<br> x,<br> y,<br> z<br>)</code></pre><p>Notice that <code>result</code> becomes an argument to the block body.</p><p>The shorthand form</p><pre><code>within f(x, y, z) :<br> body</code></pre><p>assumes that <code>f</code> takes a zero-arity function as the first argument.</p><p>The above is equivalent to this:</p><pre><code>f(<br> fn () : body<br> x,<br> y,<br> z<br>)</code></pre><p>As an example, the following creates a function that executes a body with a newly created temporary file. The function takes responsibility for creating a fresh unused file, and then deleting it after the body has finished.</p><pre><code>defn with-temporary-file (body:FileOutputStream -> ?, prefix:String) :<br> defn unused-file (i:Int) :<br> val name = to-string("%_%_.dat" % [prefix, i])<br> if file-exists?(name) : unused-file(i + 1)<br> else : name<br> val filename = unused-file(0) <br> val file = FileOutputStream(filename)<br> try :<br> body(file)<br> finally :<br> close(file)<br> delete-file(filename)</code></pre><p>The user can then use <code>with-temporary-file</code> like so:</p><pre><code>within file = with-temporary-file("temporary-dump") :<br> println(file, "This is temporary data")<br> for i in 0 to 10 do :<br> println(file, i)</code></pre><h3 id="anchor207">While Loops</h3><p>The following form creates a loop that repeats as long as a given predicate returns <code>true</code>.</p><pre><code>while p :<br> body</code></pre><h3 id="anchor208">Labeled Scopes</h3><p>The following form creates a labeled scope which returns an object of type <code>Type</code> and with an exit function named <code>myreturn</code>.</p><pre><code>label<Type> myreturn :<br> body</code></pre><p>If no explicit type is provided, then the body is assumed to return <code>false</code>, and the exit function takes no arguments.</p><pre><code>label myreturn :<br> body</code></pre><p>The most common use of labeled scopes is to return early from a function. The following example demonstrates a function that finds the first integer whose square is over <code>100</code>.</p><pre><code>defn first-big-square () :<br> label<Int> return :<br> for i in 0 to false do :<br> return(i) when i * i > 100 :<br> fatal("No such number.")</code></pre><h3 id="anchor209">Generators</h3><p>The following form generates a sequence of objects of type <code>Type</code> given the generator body. Within the body, a distinguished function called <code>yield</code> takes a single argument and includes it in the resulting sequence. A distinguished function called <code>break</code> is used to end the sequence. If no argument is passed to <code>break</code> then the sequence ends immediately. If a single argument is passed to <code>break</code> then it is included in the resulting sequence before the sequence ends.</p><pre><code>generate<Type> :<br> body</code></pre><p>If no explicit type is provided, then the default type is the unknown type.</p><pre><code>generate :<br> body</code></pre><p>The following example demonstrates a function that returns the first hundred perfect squares.</p><pre><code>generate<Int> :<br> for i in 1 through 100 do :<br> yield(i * i)</code></pre><p>To demonstrate the <code>break</code> function, the above example could also be written with a while loop like so.</p><pre><code>generate<Int> :<br> var i = 1<br> while true :<br> if i == 100 : break(i * i)<br> else : yield(i * 1)<br> i = i + 1</code></pre><h3 id="anchor210">Dynamic Variables</h3><p>The following form temporarily sets the variable <code>x</code> to the value <code>v</code> while executing the given body. The variable is restored to its original value after the body is finished.</p><pre><code>let-var x = v :<br> body</code></pre><p>If there is more than one set of bindings, then they are set and restored in parallel.</p><pre><code>let-var (x = v1, y = v2) :<br> body</code></pre><h3 id="anchor211">Exception Handling</h3><p>The following form executes a given body after installing the given exception handlers and <code>finally</code> block. Both the exception handlers and the <code>finally</code> block are optional, but a <code>try</code> expression must contain either a <code>finally</code> block or an exception handler. If the <code>finally</code> block is provided, then it is a fatal error to exit and then re-enter the body through the use of coroutines or generators.</p><pre><code>try :<br> body<br>catch (e:MyException1) :<br> handler1<br>catch (e:MyException2) :<br> handler2<br>finally :<br> cleanup</code></pre><h3 id="anchor212">Attempts and Failures</h3><p>The following form executes a given body with a given failure handler. If no <code>else</code> clause is given, then the default behaviour is to return <code>false</code>.</p><pre><code>attempt :<br> body<br>else :<br> handle failure</code></pre><h3 id="anchor213">Operators</h3><p>Operators in Stanza expand to simple function calls. The following is a listing of the core operators and their expanded form.</p><pre><code>(- x) expands to negate(x)<br>(~ x) expands to bit-not(x)<br>not x expands to complement(x)<br>x == y expands to equal?(x, y)<br>x != y expands to not-equal?(x, y)<br>x < y expands to less?(x, y)<br>x <= y expands to less-eq?(x, y)<br>x > y expands to greater?(x, y)<br>x >= y expands to greater-eq?(x, y)<br>x + y expands to plus(x, y)<br>x - y expands to minus(x, y)<br>x * y expands to times(x, y)<br>x / y expands to divide(x, y)<br>x % y expands to modulo(x, y)<br>x << y expands to shift-left(x, y)<br>x >> y expands to shift-right(x, y)<br>x >>> y expands to arithmetic-shift-right(x, y)<br>x & y expands to bit-and(x, y)<br>x | y expands to bit-or(x, y)<br>x ^ y expands to bit-xor(x, y)</code></pre><h3 id="anchor214">Anonymous Functions</h3><p>The following form creates an anonymous function with two arguments.</p><pre><code>fn (x, y) :<br> x + y</code></pre><p>If no explicit type is given for an argument then it will be inferred from the context in which the function is used. Users may optionally declare the types of the arguments and the return value using the following form.</p><pre><code>fn (x:Int, y:String) -> Char :<br> x + y</code></pre><p>To make an anonymous function tail recursive, use the <code>fn*</code> tag in place of the <code>fn</code> tag in the above forms.</p><h3 id="anchor215">Multiple Arity Functions</h3><p>The following forms creates an anonymous function with multiple arities.</p><pre><code>multifn :<br> (x) : x + 1<br> (x, y) : x + 2</code></pre><p>If no explicit type is given for an argument then it will be inferred from the context in which the function is used. Users may optionally declare the types of the arguments and the return values using the following form.</p><pre><code>multifn :<br> (x:Int) -> Int : x + 1<br> (x:Int, y:String) -> String : x + 2</code></pre><p>To make a multiple arity function tail recursive, use the <code>multifn*</code> tag in place of the <code>multifn</code> tag in the above forms.</p><h3 id="anchor216">Variable Assignments</h3><p>The following form assigns the expression <code>v</code> to the variable <code>x</code>. An assignment expression returns <code>false</code>.</p><pre><code>x = v</code></pre><h3 id="anchor217">Quasi Quote</h3><p>The <code>qquote</code> form returns an s-expression with indicated expressions substituted in.</p><pre><code>qquote(a b c)</code></pre><p>The above example returns the list <code>(a b c)</code>. The following example demonstrates the <code>~</code> substitution operator and returns the list <code>(a 3 c)</code>.</p><pre><code>val b = 3<br>qquote(a ~ b c)</code></pre><p>The following example demonstrates the <code>~@</code> splicing operator and returns the list returns the list <code>(a 1 2 3 c)</code>.</p><pre><code>val b = `(1 2 3)<br>qquote(a ~@ b c)</code></pre><h3 id="anchor218">Compile Time Flags</h3><p>The following form will define the given compile-time flag.</p><pre><code>#define(flag)</code></pre><p>The following form expands into the consequent if the given compile-time flag is defined or into the alternate otherwise.</p><pre><code>#if-defined(flag) :<br> consequent<br>#else :<br> alternate</code></pre><p>If the <code>#else</code> branch is not provided then it expands into the empty expression <code>()</code> if the flag is not defined.</p><p>The following form expands into the consequent if the given compile-time flag is not defined or into the alternate otherwise.</p><pre><code>#if-not-defined(flag) :<br> consequent<br>#else :<br> alternate</code></pre><p>If the <code>#else</code> branch is not provided then it expands into the empty expression <code>()</code> if the flag is defined.</p><h2 id="anchor219">Build System</h2><p>Stanza comes with a built-in build system for helping to build complicated Stanza projects.</p><h3 id="anchor220">Simple Project with .stanza Files</h3><p>Let's assume that your project has the following <code>.stanza</code> files:</p><p>Inside <code>mydir/fileA.stanza</code>:</p><pre><code>defpackage mypackageA :<br> import core<br> import collections<br> <br>println("This is package A")</code></pre><p>Inside <code>mydir/fileB.stanza</code>:</p><pre><code>defpackage mypackageB :<br> import core<br> import collections<br> <br>println("This is package B")</code></pre><p>Inside <code>mydir/fileC.stanza</code>:</p><pre><code>defpackage mypackageC :<br> import core<br> import collections<br> import mypackageA<br> import mypackageB<br> <br>println("This is package C")</code></pre><h3 id="anchor221">Creating a stanza.proj File</h3><p>Create the following <code>mydir/stanza.proj</code> file:</p><pre><code>package mypackageA defined-in "fileA.stanza"<br>package mypackageB defined-in "fileB.stanza"<br>package mypackageC defined-in "fileC.stanza"</code></pre><p>These statements tell the Stanza compiler which files to look in to find the definition of each Stanza package.</p><h3 id="anchor222">Calling the Compiler</h3><p>In a new shell, navigate to <code>mydir</code> and type the following to compile <code>mypackageC</code>:</p><pre><code>stanza mypackageC -o myapp</code></pre><p>This will tell the Stanza compiler to compile <code>mypackageC</code> to an application called <code>myapp</code>. Because <code>mypackageC</code> imports <code>mypackageA</code> and <code>mypackageB</code>, the Stanza compiler will pull in the files containing those packages too.</p><h3 id="anchor223">Other .proj Files</h3><p>Note that the file called <code>stanza.proj</code> is always read by the Stanza compiler to determine where files are located. If you have additional <code>.proj</code> files, e.g. <code>custom.proj</code>, you can provide them as an additional input to the Stanza compiler like so:</p><pre><code>stanza custom.proj mypackageC -o myapp</code></pre><h3 id="anchor224">Caching .pkg Files</h3><p>You can use Stanza's incremental compilation feature, by caching the `.pkg` files created by the Stanza compiler. </p><p>Create a folder called <code>mydir/pkgs</code>, and run the following command:</p><pre><code>stanza mypackageC -o myapp -pkg pkgs</code></pre><p>This will compile <code>mypackageC</code> to the application <code>myapp</code> and save any intermediate <code>.pkg</code> files to the <code>pkgs</code> folder. If you then go to compile <code>mypackageC</code> again, Stanza will pull in the cached <code>.pkg</code> files automatically if their corresponding source files have not changed.</p><h3 id="anchor225">Environment Variables</h3><p>Stanza allows the use of environment variables in the <code>.proj</code> file. Suppose that <code>fileC.stanza</code> is actually in a directory specified by the <code>FILE_C_INSTALLATION</code> environment variable. Then we can accomodate this with the following change to <code>stanza.proj</code>:</p><pre><code>package mypackageA defined-in "fileA.stanza"<br>package mypackageB defined-in "fileB.stanza"<br>package mypackageC defined-in "{FILE_C_INSTALLATION}/fileC.stanza"</code></pre><h3 id="anchor226">Packages Specified by Directory</h3><p>Stanza also provides the following shorthand for specifying the location of multiple Stanza packages as long as they obey the following naming convention.</p><pre><code>packages mysystem/utils/* defined-in "src/utils"</code></pre><p>The above statement indicates that all packages that begin with <code>mysystem/utils/</code> can be found within the directory <code>src/utils</code>.</p><p>Here are some examples of how Stanza maps package names onto filenames:</p><p>- The package <code>mysystem/utils/lists</code> will be expected to be in <code>src/utils/lists.stanza</code>.</p><p>- The package <code>mysystem/utils/arrays</code> will be expected to be in <code>src/utils/arrays.stanza</code>.</p><p>- The package <code>mysystem/utils/network/transfer</code> will be expected to be in <code>src/utils/network/transfer.stanza</code>.</p><h3 id="anchor227">Special Variables</h3><p>There are two special variables that are available to you in the <code>.proj</code> file called <code>.</code> and <code>WORKDIR</code>. </p><p>The <code>WORKDIR</code> variable refers to the absolute path to the current working directory, the directory from which the Stanza compiler was ran.</p><p>The <code>.</code> variable refers to the absolute path to the directory containing the <code>.proj</code> file. </p><p>These two special variables will be handy for compiling foreign files.</p><h3 id="anchor228">Project Structure</h3><p>Suppose that we are working on the application in the previous section of this document, and we now need to include a library project in the directory <code>/mypath/to/mylib</code>, which has its own <code>.stanza</code> files and dependency structure.</p><h3 id="anchor229">Include Statement</h3><p>Assuming that <code>mylib</code> has a <code>.proj</code> file called <code>/mypath/to/mylib/stanza.proj</code>, we can include these dependencies by modifying <code>mydir/stanza.proj</code> like so:</p><pre><code>include "/mypath/to/mylib/stanza.proj"<br>package mypackageA defined-in "fileA.stanza"<br>package mypackageB defined-in "fileB.stanza"<br>package mypackageC defined-in "fileC.stanza"</code></pre><h3 id="anchor230">Foreign File Dependencies</h3><p>Suppose that our package <code>mypackageC</code> requires some functions declared in the foreign files <code>chelpers.c</code> and <code>cpphelpers.o</code>, and needs to be compiled with the flags <code>-lmyhelpers</code>. We can tell Stanza to automatically pull in these dependencies by adding the following line to our <code>stanza.proj</code> file:</p><pre><code>package mypackageC requires :<br> ccfiles:<br> "chelpers.c"<br> "cpphelpers.o"<br> ccflags:<br> "-lmyhelpers"</code></pre><h3 id="anchor231">Platform-Specific Files and Flags</h3><p>Suppose that <code>mypackageC</code> requires the <code>-lmyhelpers</code> flag only when compiling on the <code>os-x</code> platform. We can specify this like so:</p><pre><code>package mypackageC requires :<br> ccfiles:<br> "chelpers.c"<br> "cpphelpers.o"<br> ccflags:<br> on-platform :<br> os-x : "-lmyhelpers"<br> else : ()</code></pre><h3 id="anchor232">Running a Foreign Compiler</h3><p>Suppose that <code>cpphelpers.o</code> is created by calling a foreign compiler (e.g. <code>g++</code>). We can request Stanza to run a given shell command whenever it compiles an app that depends upon <code>cpphelpers.o</code> like so:</p><pre><code>package mypackageC requires :<br> ccfiles:<br> "chelpers.c"<br> "cpphelpers.o"<br> ccflags:<br> "-lmyhelpers"<br> <br>compile file "cpphelpers.o" from "cpphelpers.cpp" :<br> "g++ {.}/cpphelpers.cpp -c -o {.}/cpphelpers.o"</code></pre><p>Note the use of the special <code>.</code> variable. Recall that it refers to the absolute path of the directory containing the <code>.proj</code> file. Our use of <code>{.}</code> allows the <code>g++</code> call to work no matter which directory it is ran from. </p><p>Note that the <code>on-platform</code> construct works for the <code>compile</code> construct as well.</p><p>If it is a flag that requires calling a foreign compiler, and not a file, then you must use the <code>compile flag</code> construct instead. Here is an example:</p><pre><code>compile flag "-lcurl" :<br> "cd mypath/to/curl && make"</code></pre><h3 id="anchor233">Conditional Imports</h3><p>Suppose that we are working on the following package <code>animals</code>, which contains the following definitions:</p><pre><code>defpackage animals :<br> import core<br> import collections<br> <br>public defstruct Dog :<br> name: String<br> weight: Double<br> breed: String</code></pre><h3 id="anchor234">Adding Support for JSON</h3><p>Now suppose that we wish to support converting <code>Dog</code> objects to JSON strings. To do this, there is a library in the package <code>json-exporter</code> containing a single multi called <code>to-json</code>, and we need to add a new method to support <code>Dog</code>.</p><pre><code>defpackage animals :<br> import core<br> import collections<br> import json-exporter<br> <br>public defstruct Dog :<br> name: String<br> weight: Double<br> breed: String<br> <br>defmethod to-json (d:Dog) :<br> to-string("{name:%~, weight:%_, breed:%~}" % [name(d), weight(d), breed(d)])</code></pre><p>However, this change makes the <code>animals</code> package dependent upon the <code>json-exporter</code> package! This means that any application that requires the <code>Dog</code> datastructure will also need to pull in the <code>json-exporter</code> package, even if the application doesn't require JSON support at all!</p><p>To overcome this, we use the conditional imports feature in the build system.</p><h3 id="anchor235">Separating the JSON functionality</h3><p>Let's move the JSON support for animals into a different package:</p><pre><code>defpackage animals/json :<br> import core<br> import collections<br> import json-exporter<br> import animals<br> <br>defmethod to-json (d:Dog) :<br> to-string("{name:%~, weight:%_, breed:%~}" % [name(d), weight(d), breed(d)])</code></pre><p>This will allow any app to optionally include the <code>animals/json</code> package if they require JSON support, or omit it if they don't. </p><h3 id="anchor236">Automatic Import</h3><p>Even better, we can ask the Stanza build system to *automatically* pull in the <code>animals/json</code> package whenever we need both the <code>animals</code> package and the <code>json-exporter</code> package together.</p><p>The resulting <code>stanza.proj</code> file looks like this:</p><pre><code>package animals defined-in "animals.stanza"<br>package animals/json defined-in "animals-json.stanza"<br>package json-exporter defined-in "json-exporter.stanza"<br>import animals/json when-imported (json-exporter, animals)</code></pre><h3 id="anchor237">Build Targets</h3><p>Suppose that the following is the final compilation command that you use to build your application:</p><pre><code>stanza mylib1 myapp -o myapplication -ccfiles "runtime.c" -optimize -pkg "mypkgs"</code></pre><p>You can store this information in a build target in your <code>stanza.proj</code> file using the following syntax:</p><pre><code>build full-application :<br> inputs:<br> mylib1<br> myapp<br> o: "myapplication"<br> ccfiles: "runtime.c"<br> pkg: "mypkgs"<br> optimize</code></pre><p>Then you can choose to build this target using the following command:</p><pre><code>stanza build full-application</code></pre><p>If no target name is provided:</p><pre><code>stanza build</code></pre><p>then Stanza will assume that there is a target named `main`. </p><p>One advantage of using build targets is that Stanza will automatically track the files that the compilation process depended upon. If these files haven't changed since you last built the target, then Stanza will print out a message like the following:</p><pre><code>Build target full-application is already up-to-date.</code></pre><h3 id="anchor238">Building Test Targets</h3><p>To support the testing framework, the user can use the <code>build-test</code> statement to define targets that compile to test runner executables:</p><pre><code>build-test tests:<br> inputs:<br> proj/tests/feature1<br> proj/tests/feature2<br> o: "unit-tests"<br> pkg: "test-pkgs"</code></pre><p>In this example the target <code>tests</code> will be built as an executable named <code>unit-tests</code>. This new executable will be compiled with the flag <code>TESTING</code> defined.</p><p>Note that it is a good idea to use the <code>pkg</code> statement to define a separate package cache directory for the unit test runner executable. Because of the added <code>TESTING</code> flag, the compiler will see normal executables and packages as being different from test executables and packages. If the same package cache directory is used for both normal and test executables, the compiler will attempt to rebuild the packages/executables every time you switch targets - instead of using the cached packages. This results in unexpectedly long build times.</p><h1 id="anchor239">Core Package</h1><p>The <code>core</code> package consists of functions and types used for basic programming.</p><h2 id="anchor240">Equalable</h2><p>Values that support the <code>equal?</code> operation are indicated as subtypes of Equalable.</p><pre><code>deftype Equalable</code></pre><p>Mandatory minimal implementation: <code>equal?</code>.</p><h3 id="anchor241">equal?</h3><p>The multi <code>equal?</code> takes as arguments two <code>Equalable</code> values and returns <code>true</code> if they are equal or <code>false</code> otherwise.</p><pre><code>defmulti equal? (a:Equalable, b:Equalable) -> True|False</code></pre><p>A default method for equal? is provided that simply returns <code>false</code>.</p><p>Equality in Stanza is defined to mean "invariant to substitution". That is, suppose that our program contains a call to a function, <code>f</code>, with a value <code>x</code>.</p><pre><code>f(x)</code></pre><p>But suppose, that earlier, we have determined that</p><pre><code>x == y</code></pre><p>returns <code>true</code>, indicating that <code>x</code> is equal to <code>y</code>. Then we should we able to substitute the usage of <code>x</code> with <code>y</code> instead without changing the behaviour of the program.</p><pre><code>f(y)</code></pre><p>Consistent to this definition, in Stanza's core library, values of immutable types are defined to be equal if their subfields are equal. Different mutable values, such as arrays, are never defined to be equal unless they refer to the same object.</p><h3 id="anchor242">not-equal?</h3><p><code>not-equal?</code> returns <code>true</code> if its two arguments are not equal and <code>false</code> otherwise.</p><pre><code>defn not-equal? (a:Equalable, b:Equalable) -> True|False</code></pre><h2 id="anchor243">Comparable</h2><p>The <code>Comparable</code> type is used to indicate that a value can compared against other values using the comparison operations. A value of type <code>Comparable<T></code> can be compared against values of type <code>T</code>.</p><pre><code>deftype Comparable<T></code></pre><p>Mandatory minimal implementation: <code>compare</code>.</p><h3 id="anchor244">compare</h3><p>The following multi compares values of type <code>Comparable<T></code> against values of type <code>T</code>. The multi returns a negative integer if the item <code>a</code> is less than the item <code>b</code>, zero if the two are equal, and a positive integer if the item <code>a</code> is greater than the item <code>b</code>. For values that are subtypes of both <code>Equalable</code> and <code>Comparable</code>, the compare operation must be consistently defined against the <code>equal?</code> operation, and return <code>0</code> if <code>equal?</code> returns <code>true</code>.</p><pre><code>defmulti compare<?T> (a:Comparable<?T>, b:T) -> Int</code></pre><h3 id="anchor245">less?, greater?, less-eq?, greater-eq?</h3><p>The following multis are provided for subtypes to provide efficient implementations. Any defined method must return results consistent with the compare operation. Default methods are provided for these multis defined in terms of the <code>compare</code> operation.</p><pre><code>defmulti less?<?T> (a:Comparable<?T>, b:T) -> True|False<br>defmulti greater?<?T> (a:Comparable<?T>, b:T) -> True|False<br>defmulti less-eq?<?T> (a:Comparable<?T>, b:T) -> True|False<br>defmulti greater-eq?<?T> (a:Comparable<?T>, b:T) -> True|False</code></pre><h3 id="anchor246">max, min</h3><p>The following functions compute the maximum or minimum of their two given arguments.</p><pre><code>defn max<?T,?S> (a:?S&Comparable<?T>, b:T) -> S|T<br>defn min<?T,?S> (a:?S&Comparable<?T>, b:T) -> S|T</code></pre><h3 id="anchor247">maximum, minimum</h3><p>The following functions compute the minimum between an initial value <code>x0</code>, and a sequence of items <code>xs</code> using the provided comparison function. If no initial value is provided, then the sequence <code>xs</code> cannot be empty.</p><pre><code>defn minimum<?T> (x0:T, xs:Seqable<?T>, less?: (T, T) -> True|False) -> T<br>defn minimum<?T> (xs:Seqable<?T>, less?: (T, T) -> True|False) -> T</code></pre><p>The following functions compute the maximum between an initial value <code>x0</code>, and a sequence of items <code>xs</code> using the provided comparison function. If no initial value is provided, then the sequence <code>xs</code> cannot be empty.</p><pre><code>defn maximum<?T> (x0:T, xs:Seqable<?T>, less?: (T, T) -> True|False) -> T<br>defn maximum<?T> (xs:Seqable<?T>, less?: (T, T) -> True|False) -> T</code></pre><p>The following functions compute the minimum between an initial value <code>x0</code>, and a sequence of comparable items <code>xs</code> using the <code>less?</code> multi. If no initial value is provided, then the sequence <code>xs</code> cannot be empty.</p><pre><code>defn minimum<?T> (x0:T&Comparable, xs:Seqable<?T&Comparable>) -> T<br>defn minimum<?T> (xs:Seqable<?T&Comparable>) -> T</code></pre><p>The following functions compute the maximum between an initial value <code>x0</code>, and a sequence of comparable items <code>xs</code> using the <code>less?</code> multi. If no initial value is provided, then the sequence <code>xs</code> cannot be empty.</p><pre><code>defn maximum<?T> (x0:T&Comparable, xs:Seqable<?T&Comparable>) -> T<br>defn maximum<?T> (xs:Seqable<?T&Comparable>) -> T</code></pre><p>The following function returns the minimum in a sequence of items <code>xs</code> by comparing the keys extracted from each item using the provided <code>key</code> function.</p><pre><code>defn minimum<?T> (key: T -> Comparable, xs:Seqable<?T>) -> T</code></pre><p>The following function returns the maximum in a sequence of items <code>xs</code> by comparing the keys extracted from each item using the provided <code>key</code> function.</p><pre><code>defn maximum<?T> (key: T -> Comparable, xs:Seqable<?T>) -> T</code></pre><h2 id="anchor248">Hashable</h2><p>The type <code>Hashable</code> indicates that a value supports the <code>hash</code> multi and can represented (non-uniquely) as an <code>Int</code> value.</p><pre><code>deftype Hashable</code></pre><p>Mandatory minimal implementation: <code>hash</code>.</p><h3 id="anchor249">hash</h3><p>The <code>hash</code> multi takes a <code>Hashable</code> argument and returns an <code>Int</code>. For the correct operation of <code>HashTable</code> implementations, the definition of <code>hash</code> must be consistent with the definition of <code>equal?</code>. If two values are equal, then they must also return the same hash.</p><pre><code>defmulti hash (h:Hashable) -> Int</code></pre><h2 id="anchor250">Lengthable</h2><p>A <code>Lengthable</code> is a value that has an unknown length.</p><pre><code>deftype Lengthable</code></pre><p>Mandatory minimal implementation: <code>length</code>.</p><h3 id="anchor251">length</h3><p>The <code>length</code> multi calculates the length of a <code>Lengthable</code> object.</p><pre><code>defmulti length (l:Lengthable) -> Int</code></pre><h2 id="anchor252">Seq</h2><p>A <code>Seq</code> represents a possibly infinite sequence of items of type <code>T</code>.</p><pre><code>deftype Seq<T> <: Seqable<T></code></pre><p>Mandatory minimal implementation: <code>empty?</code>, <code>next</code>.</p><h3 id="anchor253">empty?</h3><p>The <code>empty?</code> multi returns <code>true</code> if the sequence contains more items, or <code>false</code> otherwise.</p><pre><code>defmulti empty? (s:Seq) -> True|False</code></pre><h3 id="anchor254">next</h3><p>The <code>next</code> multi returns the next item in the sequence. Repeated calls to <code>next</code> results in successive items in the sequence being returned. It is a fatal error to call <code>next</code> on an empty sequence.</p><pre><code>defmulti next<?T> (s:Seq<?T>) -> T</code></pre><h2 id="anchor255">PeekSeq</h2><p>A <code>PeekSeq</code> is derived from <code>Seq</code> and adds the ability to "peek" at the next element in a sequence.</p><pre><code>deftype PeekSeq<T> : Seq<T></code></pre><p>Mandatory minimal implementation: <code>empty?</code>, <code>next</code>, <code>peek</code>.</p><h3 id="anchor256">peek</h3><p>The <code>peek</code> multi inspects the next item in the sequence but does not consume it. Repeated calls to <code>peek</code> results in the same item being returned. It is a fatal error to call <code>peek</code> on an empty sequence.</p><pre><code>defmulti peek<?T> (s:PeekSeq<?T>) -> T</code></pre><h2 id="anchor257">Seqable</h2><p>A <code>Seqable</code> represents any object that may be viewed as a sequence of items of type <code>T</code>.</p><pre><code>deftype Seqable<T></code></pre><p>Mandatory minimal implementation: <code>to-seq</code>.</p><h3 id="anchor258">to-seq</h3><p>The <code>to-seq</code> multi returns a <code>Seq</code> representing a sequential view of the contents of the given object <code>s</code>.</p><pre><code>defmulti to-seq<?T> (s:Seqable<?T>) -> Seq<T></code></pre><p>A value of type <code>Seq</code> is defined to also be a <code>Seqable</code> and trivially returns itself when called with <code>to-seq</code>.</p><h2 id="anchor259">Collection</h2><p>Similar to <code>Seqable</code>, a <code>Collection</code> also represents an object that may be viewed as a sequence of items of type <code>T</code>. The crucial difference between a <code>Collection</code> and <code>Seqable</code> is that a <code>Collection</code> must be <span style="font-style:italic;">repeatedly</span> viewable as a sequence of items.</p><p>As an example, consider a function, <code>print-all-twice</code>, that iterates through and prints out the items in a sequence twice.</p><pre><code>defn print-all-twice (xs:Seqable) -> False :<br> val seq1 = to-seq(xs)<br> while not empty?(seq1) :<br> println(next(seq1))<br><br> val seq2 = to-seq(xs)<br> while not empty?(seq2) :<br> println(next(seq2))</code></pre><p>Such a function would not work as expected when called with a <code>Seq</code>. Recall that calling <code>to-seq</code> on a <code>Seq</code> is a trivial operation that returns the <code>Seq</code> directly. Thus the first while loop will print out every item in the sequence, but the second while loop will not complete a single iteration as the sequence is already empty. The correct type signature for <code>print-all-twice</code> would be</p><pre><code>defn print-all-twice (xs:Collection) -> False</code></pre><p><code>Seq</code> is a subtype of <code>Seqable</code>, but not a subtype of <code>Collection</code>. Thus the new type signature correctly disallows <code>print-all-twice</code> from being called with objects of type <code>Seq</code>.</p><p>Mandatory minimal implementation: <code>to-seq</code>.</p><h2 id="anchor260">IndexedCollection</h2><p>An <code>IndexedCollection</code> represents a mutable collection containing a series of items, each of which is associated with an integer index.</p><code>deftype IndexedCollection<T> <: Lengthable & Collection<T></code><p>All <code>IndexedCollections</code> are subtypes of <code>Collection</code> and support the <code>to-seq</code> operation. A default method for <code>to-seq</code> defined in terms of <code>length</code> and <code>get</code> is provided. For efficiency purposes, subtypes of <code>IndexedCollections</code> may provide a customized method of <code>to-seq</code>, but it is not required.</p><p>Mandatory minimal implementation: <code>length</code>, <code>get(IndexedCollection<T>, Int)</code>, <code>set(IndexedCollection<T>, Int, T)</code>.</p><h3 id="anchor261">get, set</h3><p>Appropriate methods for getting and setting an item at a given index <code>i</code> must be provided for all subtypes. <code>get</code> retrieves the object at integer index <code>i</code> in the object <code>a</code>. <code>set</code> assigns the value <code>v</code> to the object <code>a</code> at integer index <code>i</code>. The index <code>i</code> must be non-negative and less than the length of <code>a</code>.</p><pre><code>defmulti get<?T> (a:IndexedCollection<?T>, i:Int) -> T<br>defmulti set<?T> (a:IndexedCollection<?T>, i:Int, v:T) -> False</code></pre><h3 id="anchor262">get</h3><p>The following function returns a range of items in an <code>IndexedCollection</code>. The given range must be a <span style="font-style:italic;">dense index range</span> with respect to the collection <code>a</code>. A default method defined in terms of <code>get</code> is provided, but subtypes may provide customized methods for efficiency purposes if desired.</p><pre><code>defmulti get<?T> (a:IndexedCollection<?T>, r:Range) -> Collection<T></code></pre><h3 id="anchor263">set</h3><p>The following function sets a range of indices within the collection to items taken sequentially from <code>vs</code>. The given range must be a <span style="font-style:italic;">dense index range</span> with respect to the collection <code>a</code>. The sequence <code>vs</code> must contain at least as many items as indices being assigned. A default method defined in terms of <code>set</code> is provided, but subtypes may provide customized methods for efficiency purposes if desired.</p><pre><code>defmulti set<?T> (a:IndexedCollection<?T>, r:Range, vs:Seqable<T>) -> False</code></pre><h3 id="anchor264">map!</h3><p>The following function iterates through the given collection and replaces each item with the result of calling <code>f</code> on the item. A default method defined in terms of <code>get</code> and <code>set</code> is provided, but subtypes may provide customized methods for efficiency purposes if desired.</p><pre><code>defmulti map!<?T> (f: T -> T, xs:IndexedCollection<?T>) -> False</code></pre><h3 id="anchor265">empty?</h3><p><code>empty?</code> returns <code>true</code> if the collection is empty or <code>false</code> otherwise.</p><pre><code>defn empty? (v:IndexedCollection) -> True|False</code></pre><h3 id="anchor266">reverse!</h3><p>The following function reverses the order in which items appear in the collection.</p><pre><code>defn reverse!<?T> (xs:IndexedCollection<?T>) -> False</code></pre><h3 id="anchor267">in-reverse</h3><p>The following function returns a sequence containing the items in the collection in reversed order. The original collection is unchanged.</p><pre><code>defn in-reverse<?T> (xs:IndexedCollection<?T>) -> Seq<T></code></pre><h2 id="anchor268">OutputStream</h2><p>An <code>OutputStream</code> represents a destination to which we can print characters, and write values. The most common output stream used in daily programming is the standard output stream which represents the user's terminal.</p><pre><code>deftype OutputStream</code></pre><p>Mandatory minimal implementation: <code>print(OutputStream, Char)</code>.</p><h3 id="anchor269">print</h3><p>The fundamental operation for an <code>OutputStream</code> is the function for printing a specific value <code>x</code> to the output stream.</p><pre><code>defmulti print (o:OutputStream, x) -> False</code></pre><p>For all types in the core Stanza library, there is a default implementation of <code>print</code> for that type that prints each <code>Char</code> in its string representation to the output stream. Because of this, the only mandatory method that needs to be implemented by subtypes of <code>OutputStream</code> is that for <code>Char</code>.</p><pre><code>defmethod print (o:OutputStream, c:Char) -> False</code></pre><h3 id="anchor270">print-all</h3><p><code>print-all</code> prints all the item in the given sequence to the <code>OutputStream</code>.</p><pre><code>defmulti print-all (o:OutputStream, xs:Seqable) -> False</code></pre><p>There is a default method implemented for <code>print-all</code> that calls <code>print</code> on each item in the sequence. For efficiency purposes, users are free to provide customized versions of <code>print-all</code> for specific types.</p><h3 id="anchor271">println</h3><p><code>println</code> prints the item <code>x</code> to the <code>OutputStream</code> followed by the newline character.</p><pre><code>defn println (o:OutputStream, x) -> False</code></pre><h3 id="anchor272">println-all</h3><p><code>println-all</code> prints all items in the sequence <code>xs</code> to the <code>OutputStream</code> followed by the newline character.</p><pre><code>defn println-all (o:OutputStream, xs:Seqable) -> False</code></pre><h3 id="anchor273">STANDARD-OUTPUT-STREAM</h3><p>This global value holds the standard output stream representing the user's terminal.</p><pre><code>val STANDARD-OUTPUT-STREAM : OutputStream</code></pre><h3 id="anchor274">with-output-stream</h3><p>The current output stream is, by default, the standard output stream. The following function will set the current output stream to <code>o</code> before calling the function <code>f</code> and then restore the current output stream afterwards.</p><pre><code>defn with-output-stream<?T> (o:OutputStream, f: () -> ?T) -> T</code></pre><h3 id="anchor275">current-output-stream</h3><p>The current output stream may be retrieved with the following function.</p><pre><code>defn current-output-stream () -> OutputStream</code></pre><h3 id="anchor276">print to current OutputStream</h3><p>The following functions behave identically to the versions that do not take an OutputStream argument. Instead they print to the current output stream.</p><pre><code>defn print (x) -> False<br>defn println (x) -> False<br>defn print-all (xs:Seqable) -> False<br>defn println-all (xs:Seqable) -> False</code></pre><h3 id="anchor277">Standard Error</h3><p>Similar to the standard output facilities described above, standard error can be accessed and overriden with similar functions:</p><pre><code>val STANDARD-ERROR-STREAM : OutputStream<br>defn with-error-stream<?T> (o:OutputStream, body: () -> ?T) -> T<br>defn current-error-stream () -> OutputStream</code></pre><p>It is good practice not to reference <code>STANDARD-ERROR-STREAM</code> directly but to instead use the <code>current-error-stream()</code> function to access the standard error stream buffer.</p><h2 id="anchor278">InputStream</h2><p>An <code>InputStream</code> represents a source from which we can read characters and values.</p><pre><code>deftype InputStream</code></pre><p>Mandatory minimal implementation: <code>get-char</code>, <code>get-byte</code>.</p><h3 id="anchor279">get-char</h3><p>This multi reads a single character from the given input stream. <code>false</code> is returned if there are no more characters in the stream.</p><pre><code>defn get-char (i:InputStream) -> Char|False</code></pre><h3 id="anchor280">get-byte</h3><p>The following function reads a single byte from the given input stream. <code>false</code> is returned if there are no more bytes in the stream.</p><pre><code>defn get-byte (i:InputStream) -> Byte|False</code></pre><h3 id="anchor281">STANDARD-INPUT-STREAM</h3><p>This global value holds the standard input stream representing the user's terminal.</p><pre><code>val STANDARD-INPUT-STREAM : InputStream</code></pre><h3 id="anchor282">fill</h3><p>The following multi reads characters continuously from the input stream and stores them into the given <code>CharArray</code> at the specified range. The range must be a <span style="font-style:italic;">dense index range</span> with respect to <code>xs</code>. The number of characters read is returned.</p><pre><code>defmulti fill (xs:CharArray, r:Range, i:InputStream) -> Int</code></pre><p>A default method implemented in terms of <code>get-char</code> is provided, but for efficiency purposes, users are free to provide customized methods for subtypes of <code>InputStream</code>.</p><h2 id="anchor283">IndentedStream</h2><p>An <code>IndentedStream</code> wraps over an <code>OutputStream</code> to provide the ability to automatically print indenting spaces as needed.</p><pre><code>deftype IndentedStream <: OutputStream</code></pre><p><code>IndentedStream</code> is a subtype of <code>OutputStream</code> and can be used as a target for the <code>print</code> function. When asked to print a newline character, an <code>IndentedStream</code> will print the newline character followed by the number of spaces indicated during creation of the stream. For all other characters, an <code>IndentedStream</code> simply calls print on its wrapped <code>OutputStream</code>.</p><h3 id="anchor284">IndentedStream</h3><p>This function creates an <code>IndentedStream</code> that indents <code>n</code> spaces by wrapping over the given <code>OutputStream</code>.</p><pre><code>defn IndentedStream (o:OutputStream, n:Int) -> IndentedStream</code></pre><h3 id="anchor285">do-indented</h3><p>This function calls the function <code>f</code> with a new <code>IndentedStream</code> created by wrapping over the given output stream.</p><pre><code>defn do-indented<?T> (f: IndentedStream -> ?T, o:OutputStream) -> T</code></pre><h3 id="anchor286">indented</h3><p>This function wraps over the current output stream with an <code>IndentedStream</code> and then calls the function <code>f</code>. The current output stream is restored afterwards.</p><pre><code>defn indented<?T> (f: () -> ?T) -> T</code></pre><h2 id="anchor287">FileOutputStream</h2><p>A <code>FileOutputStream</code> represents an external file with an output stream interface to which we can write values.</p><pre><code>deftype FileOutputStream <: OutputStream</code></pre><p>A <code>FileOutputStream</code> is a subtype of <code>OutputStream</code> and can be used as a target for the <code>print</code> function.</p><h3 id="anchor288">FileOutputStream</h3><p>These functions create a new <code>FileOutputStream</code> given the path to the file, and a boolean flag indicating, in the case that the file already exists, whether new characters should be appended to the end of the file or whether the file should be overwritten. If no <code>append?</code> flag is given, then by default, the file is overwritten.</p><pre><code>defn FileOutputStream (filename:String, append?:True|False) -> FileOutputStream<br>defn FileOutputStream (filename:String) -> FileOutputStream</code></pre><h3 id="anchor289">put</h3><p>These functions write the following values as binary data following little endian conventions.</p><pre><code>defn put (o:FileOutputStream, x:Byte) -> False<br>defn put (o:FileOutputStream, x:Int) -> False<br>defn put (o:FileOutputStream, x:Long) -> False<br>defn put (o:FileOutputStream, x:Float) -> False<br>defn put (o:FileOutputStream, x:Double) -> False</code></pre><h3 id="anchor290">close</h3><p>This function closes a <code>FileOutputStream</code>.</p><pre><code>defn close (o:FileOutputStream) -> False</code></pre><h3 id="anchor291">with-output-file</h3><p>This function sets the given file as the current output stream before calling the function <code>f</code>. Afterwards, it restores the current output stream and closes the file.</p><pre><code>defn with-output-file<?T> (file:FileOutputStream, f: () -> ?T) -> T</code></pre><h3 id="anchor292">spit</h3><p>This function prints the given object to the given file.</p><pre><code>defn spit (filename:String, x) -> False</code></pre><h2 id="anchor293">Pretty Printing</h2><p>The following pretty printing functions are used for printing a value in a form that preserves its structure. For example, <code>String</code> objects are surrounded in quotes and non-printable characters are escaped. Numbers have suffixes to indicate their type. For the core types that make up an s-expression, values are written out in a form that can be read back in using the reader.</p><h3 id="anchor294">write</h3><p>The write multi pretty prints the given object <code>x</code>. A default method is provided that simply calls <code>print</code>. Objects whose pretty printed representations differ from their printed representations should provide a custom method for <code>write</code>.</p><pre><code>defmulti write (o:OutputStream, x) -> False</code></pre><h3 id="anchor295">write-all</h3><p>This function pretty prints every item in the sequence <code>xs</code> separated by spaces.</p><pre><code>defn write-all (o:OutputStream, xs:Seqable) -> False</code></pre><h2 id="anchor296">FileInputStream</h2><p>A <code>FileInputStream</code> represents an external file with an input stream interface from which we can read values.</p><pre><code>deftype FileInputStream <: InputStream</code></pre><p><code>FileInputStream</code> is a subtype of <code>InputStream</code> and supports the fundamental operations, <code>get-char</code> and <code>get-byte</code>, for reading a character or a byte from the stream.</p><h3 id="anchor297">FileInputStream</h3><p>This function creates a <code>FileInputStream</code> given the name of the file.</p><pre><code>defn FileInputStream (filename:String) -> FileInputStream</code></pre><h3 id="anchor298">close</h3><p>This function closes a <code>FileInputStream</code>.</p><pre><code>defn close (i:FileInputStream) -> False</code></pre><h3 id="anchor299">Reading Values</h3><p>These functions read values as binary data following little endian conventions.</p><pre><code>defn get-int (i:FileInputStream) -> False|Int<br>defn get-long (i:FileInputStream) -> False|Long<br>defn get-float (i:FileInputStream) -> False|Float<br>defn get-double (i:FileInputStream) -> False|Double</code></pre><h3 id="anchor300">slurp</h3><p>This function reads the entire contents of a file and returns the contents as a <code>String</code>.</p><pre><code>defn slurp (filename:String) -> String</code></pre><h2 id="anchor301">StringInputStream</h2><p>A <code>StringInputStream</code> represents an input stream backed by an underlying string.</p><pre><code>deftype StringInputStream <: InputStream & Lengthable</code></pre><p><code>StringInputStream</code> is a subtype of <code>InputStream</code> and implements appropriate methods for reading characters and bytes.</p><p><code>StringInputStream</code> is a subtype of <code>Lengthable</code> and implements an appropriate method for the <code>length</code> multi that returns the number of characters left unread in the underlying string.</p><h3 id="anchor302">StringInputStream</h3><p>This function creates a <code>StringInputStream</code> given the underlying string and the name of the file that it comes from. If no filename is given, then its default value is <code>"UnnamedStream"</code>.</p><pre><code>defn StringInputStream (string:String, filename:String) -> StringInputStream<br>defn StringInputStream (string:String) -> StringInputStream</code></pre><h3 id="anchor303">peek?</h3><p>A <code>StringInputStream</code> allows for the characters beyond the immediate following character to be read. The following function returns the <code>i</code>'th next character in the stream, if one exists. If the index <code>i</code> is not given, then its default value is <code>0</code>.</p><pre><code>defn peek? (s:StringInputStream, i:Int) -> False|Char<br>defn peek? (s:StringInputStream) -> False|Char</code></pre><h3 id="anchor304">info</h3><p><code>StringInputStream</code> keeps track of the current position of its read marker. The following function returns the <code>FileInfo</code> representing the current position in the string.</p><pre><code>defn info (s:StringInputStream) -> FileInfo</code></pre><h2 id="anchor305">RandomAccessFile</h2><p>A <code>RandomAccessFile</code> represents an external file that allows users to read and write at non-consecutive locations.</p><pre><code>deftype RandomAccessFile</code></pre><h3 id="anchor306">RandomAccessFile</h3><p>This function creates a <code>RandomAccessFile</code> for the given filename and boolean flag for indicating whether the file should be writable. A <code>FileOpenException</code> is thrown if the file could not be opened.</p><pre><code>defn RandomAccessFile (filename:String, writable:True|False) -> RandomAccessFile</code></pre><h3 id="anchor307">close</h3><p>This function flushes all pending writes and closes an open <code>RandomAccessFile</code>. A <code>FileCloseException</code> is thrown if the file could not be closed.</p><pre><code>defn close (file:RandomAccessFile) -> False</code></pre><h3 id="anchor308">writable?</h3><p>This function returns <code>true</code> if the given file is writable, or false otherwise.</p><pre><code>defn writable? (file:RandomAccessFile) -> True|False</code></pre><h3 id="anchor309">length</h3><p>This function returns the length in bytes for the given file.</p><pre><code>defn length (file:RandomAccessFile) -> Long</code></pre><h3 id="anchor310">set-length</h3><p>This function sets the length in bytes of the given file to the given value. If the current length of the file is greater than the given length, then the file is truncated. If the current length is less than the given length, then the file is padded with undefined values until the given length. A <code>FileSetLengthException</code> is thrown if the operation is not successful.</p><pre><code>defn set-length (file:RandomAccessFile, length:Long) -> False</code></pre><h3 id="anchor311">seek</h3><p>This function sets the read/write cursor of the file to the given position. A <code>FileSeekException</code> is thrown if the operation is not successful.</p><pre><code>defn seek (file:RandomAccessFile, pos:Long) -> False</code></pre><h3 id="anchor312">skip</h3><p>This function increments the read/write cursor of the file by <code>pos</code> number of bytes. The cursor can be moved backwards towards the beginning of the file by providing a negative <code>pos</code>. A <code>FileSeekException</code> is thrown if the operation is not successful.</p><pre><code>defn skip (file:RandomAccessFile, pos:Long) -> False</code></pre><h3 id="anchor313">Reading Values</h3><p>These functions read values as binary data following little endian conventions from the given file. The functions either return the value read, or <code>false</code> if it has reached the end of the file. A <code>FileReadException</code> is thrown if the operations are not successful.</p><pre><code>defn get-byte (file:RandomAccessFile) -> Byte|False<br>defn get-char (file:RandomAccessFile) -> Char|False<br>defn get-int (file:RandomAccessFile) -> Int|False<br>defn get-long (file:RandomAccessFile) -> Long|False<br>defn get-float (file:RandomAccessFile) -> Float|False<br>defn get-double (file:RandomAccessFile) -> Double|False</code></pre><h3 id="anchor314">Writing Values</h3><p>These functions write values as binary data following little endian conventions into the given file. A <code>FileWriteException</code> is thrown if the operations are not successful.</p><pre><code>defn put (file:RandomAccessFile, x:Byte) -> False<br>defn put (file:RandomAccessFile, x:Char) -> False<br>defn put (file:RandomAccessFile, x:Int) -> False<br>defn put (file:RandomAccessFile, x:Long) -> False<br>defn put (file:RandomAccessFile, x:Float) -> False<br>defn put (file:RandomAccessFile, x:Double) -> False</code></pre><h3 id="anchor315">Reading Blocks</h3><p>This function reads contiguous bytes from the given file and stores them into the range <code>r</code> in the byte array <code>a</code>. <code>r</code> must be a dense index range with respect to <code>a</code>. The number of bytes read is returned by the function. A <code>FileReadException</code> is thrown if the operation is not successful.</p><pre><code>defn fill (a:ByteArray, r:Range, file:RandomAccessFile) -> Long</code></pre><p>If the range <code>r</code> is not given, then the function stores the read bytes starting from the beginning of the array <code>a</code> and proceeds until the end. </p><pre><code>defn fill (a:ByteArray, file:RandomAccessFile) -> Long</code></pre><h3 id="anchor316">Writing Blocks</h3><p>This function writes contiguous bytes from the range <code>r</code> in the given byte array <code>xs</code> into the given file. <code>r</code> must be a dense index range with respect to <code>xs</code>. A <code>FileWriteException</code> is thrown if the operation is not successful.</p><pre><code>defn put (file:RandomAccessFile, xs:ByteArray, r:Range) -> False</code></pre><p>If the range <code>r</code> is not given, then the function writes the entire array <code>xs</code> into the file.</p><pre><code>defn put (file:RandomAccessFile, xs:ByteArray) -> False</code></pre><h2 id="anchor317">Numbers</h2><p>The following types make up Stanza's basic numerical types.</p><pre><code>deftype Byte <: Equalable & Hashable & Comparable<Byte><br>deftype Int <: Equalable & Hashable & Comparable<Int><br>deftype Long <: Equalable & Hashable & Comparable<Long><br>deftype Float <: Equalable & Hashable & Comparable<Float><br>deftype Double <: Equalable & Hashable & Comparable<Double></code></pre><p>A <code>Byte</code> represents an 8-bit unsigned integer between <code>0</code> and <code>255</code> (inclusive). An <code>Int</code> represents a 32-bit signed integer. A <code>Long</code> represents a 64-bit signed integer. A <code>Float</code> represents a 32-bit real number in IEEE 754 encoding. A <code>Double</code> represents a 64-bit real number in IEEE 754 encoding.</p><p>Each of the numerical types are subtypes of <code>Equalable</code>, and hence support the <code>equal?</code> multi. Note that numerical values of different types are never defined to be equal to one another. Thus the <code>Int</code>, <code>0</code>, is not equal to the <code>Long</code>, <code>0L</code>.</p><p>Each of the numerical types are subtypes of <code>Comparable</code>, and can be compared against themselves.</p><p>Each of the numerical types are subtypes of <code>Hashable</code>, and supports the <code>hash</code> multi.</p><h3 id="anchor318">Numeric Literals</h3><p>Due to the separate types for each number, distinct numeric literal forms are required for each. Below are examples:</p><pre><code>val kB : Double = 1.38e-23<br>val kB_f : Float = 1.38e-23F<br><br>val R : Float = 8.314f<br><br>val Meaning : Int = 42<br>val Meaning_L : Long = 42L<br>val Prime-6 : Long = 13l<br><br>val ascii-0 : Byte = 48Y<br>val ascii-1 : Byte = 0x31y<br></code></pre><p>Note that the suffix can be either lower or upper case. There is no space between the last number digit and the suffix character. </p><h3 id="anchor319">Integer Arithmetic</h3><p>Integer numerical types support the standard arithmetic operations.</p><pre><code>defn plus (x:Byte, y:Byte) -> Byte<br>defn minus (x:Byte, y:Byte) -> Byte<br>defn times (x:Byte, y:Byte) -> Byte<br>defn divide (x:Byte, y:Byte) -> Byte<br>defn modulo (x:Byte, y:Byte) -> Byte</code></pre><pre><code>defn plus (x:Int, y:Int) -> Int<br>defn minus (x:Int, y:Int) -> Int<br>defn times (x:Int, y:Int) -> Int<br>defn divide (x:Int, y:Int) -> Int<br>defn modulo (x:Int, y:Int) -> Int</code></pre><pre><code>defn plus (x:Long, y:Long) -> Long<br>defn minus (x:Long, y:Long) -> Long<br>defn times (x:Long, y:Long) -> Long<br>defn divide (x:Long, y:Long) -> Long<br>defn modulo (x:Long, y:Long) -> Long</code></pre><h3 id="anchor320">Floating Point Arithmetic</h3><p>Floating point numerical types support the all standard arithmetic operations except the modulo operation.</p><pre><code>defn plus (x:Float, y:Float) -> Float<br>defn minus (x:Float, y:Float) -> Float<br>defn times (x:Float, y:Float) -> Float<br>defn divide (x:Float, y:Float) -> Float</code></pre><pre><code>defn plus (x:Double, y:Double) -> Double<br>defn minus (x:Double, y:Double) -> Double<br>defn times (x:Double, y:Double) -> Double<br>defn divide (x:Double, y:Double) -> Double</code></pre><p>Note that arithmetic operations must be performed between values of the same numerical type. Users must manually convert values from one type to another if their types differ.</p><p>In addition, the user can access the <code>nan?</code> function to check for "Not a Number" conditions.</p><pre><code>defn nan? (x:Double) -> True|False<br>defn nan? (x:Float) -> True|False</code></pre><p>Below are some additional helper values related to floating point values. These can be useful for unit tests:</p><pre><code>val FLOAT-NAN : Float<br>val FLOAT-POSITIVE-INFINITY : Float<br>val FLOAT-NEGATIVE-INFINITY : Float<br><br>val DOUBLE-NAN : Double<br>val DOUBLE-POSITIVE-INFINITY : Double<br>val DOUBLE-NEGATIVE-INFINITY : Double</code></pre><h3 id="anchor321">Signed Arithmetic</h3><p>All numerical values except of type <code>Byte</code> support the additional negation and absolute value operations. <code>Byte</code> values are unsigned and hence do not support these operations.</p><pre><code>defn negate (x:Int) -> Int<br>defn negate (x:Long) -> Long<br>defn negate (x:Double) -> Double<br>defn negate (x:Float) -> Float</code></pre><pre><code>defn abs (x:Int) -> Int<br>defn abs (x:Long) -> Long<br>defn abs (x:Double) -> Double<br>defn abs (x:Float) -> Float</code></pre><h3 id="anchor322">Bitwise Operations</h3><p>Integer numerical types support the standard bitwise operations.</p><pre><code>defn shift-left (x:Byte, y:Byte) -> Byte<br>defn shift-right (x:Byte, y:Byte) -> Byte<br>defn bit-or (x:Byte, y:Byte) -> Byte<br>defn bit-and (x:Byte, y:Byte) -> Byte<br>defn bit-xor (x:Byte, y:Byte) -> Byte<br>defn bit-not (x:Byte) -> Byte</code></pre><pre><code>defn shift-left (x:Int, y:Int) -> Int<br>defn shift-right (x:Int, y:Int) -> Int<br>defn arithmetic-shift-right (x:Int, y:Int) -> Int<br>defn bit-or (x:Int, y:Int) -> Int<br>defn bit-and (x:Int, y:Int) -> Int<br>defn bit-xor (x:Int, y:Int) -> Int<br>defn bit-not (x:Int) -> Int</code></pre><pre><code>defn shift-left (x:Long, y:Long) -> Long<br>defn shift-right (x:Long, y:Long) -> Long<br>defn arithmetic-shift-right (x:Long, y:Long) -> Long<br>defn bit-or (x:Long, y:Long) -> Long<br>defn bit-and (x:Long, y:Long) -> Long<br>defn bit-xor (x:Long, y:Long) -> Long<br>defn bit-not (x:Long) -> Long</code></pre><h3 id="anchor323">Numerical Limits</h3><p>The maximum and minimum values for the integer numerical types are defined in the following global values.</p><pre><code>val BYTE-MAX : Byte<br>val BYTE-MIN : Byte<br>val INT-MAX : Int<br>val INT-MIN : Int<br>val LONG-MAX : Long<br>val LONG-MIN : Long<br><br>val FLOAT-MAX : Float<br>val FLOAT-MIN-NORMAL : Float<br>val FLOAT-MIN : Float<br><br>val DOUBLE-MAX : Double<br>val DOUBLE-MIN-NORMAL : Double<br>val DOUBLE-MIN : Double<br></code></pre><h3 id="anchor324">Numerical Conversion</h3><p>Numerical types can be converted from one type to another using the following functions.</p><pre><code>defn to-byte (b:Byte) -> Byte<br>defn to-byte (i:Int) -> Byte<br>defn to-byte (l:Long) -> Byte<br>defn to-byte (f:Float) -> Byte<br>defn to-byte (d:Double) -> Byte<br>defn to-int (b:Byte) -> Int<br>defn to-int (i:Int) -> Int<br>defn to-int (l:Long) -> Int<br>defn to-int (f:Float) -> Int<br>defn to-int (d:Double) -> Int<br>defn to-long (b:Byte) -> Long<br>defn to-long (i:Int) -> Long<br>defn to-long (l:Long) -> Long<br>defn to-long (f:Float) -> Long<br>defn to-long (d:Double) -> Long<br>defn to-float (b:Byte) -> Float<br>defn to-float (i:Int) -> Float<br>defn to-float (l:Long) -> Float<br>defn to-float (f:Float) -> Float<br>defn to-float (d:Double) -> Float<br>defn to-double (b:Byte) -> Double<br>defn to-double (i:Int) -> Double<br>defn to-double (l:Long) -> Double<br>defn to-double (f:Float) -> Double<br>defn to-double (d:Double) -> Double</code></pre><p>Integer types can be converted without loss of precision from a type with less bits to a type with more bits. When converting from a type with more bits to a type with less bits, the most significant bits are truncated.</p><p>When converting integer types to floating point types, the closest floating point number is returned.</p><h3 id="anchor325">bits</h3><p><code>bits</code> returns an integer type whose bit representation is equivalent to the IEEE754 bit representation of the given floating point number.</p><pre><code>defn bits (x:Float) -> Int<br>defn bits (x:Double) -> Long</code></pre><h3 id="anchor326">bits-as-float, bits-as-double</h3><p><code>bits-as-float</code> and <code>bits-as-double</code> returns a floating point number whose IEEE754 bit representation is equivalent to the bit representation of the given integer.</p><pre><code>defn bits-as-float (x:Int) -> Float<br>defn bits-as-double (x:Long) -> Double</code></pre><h3 id="anchor327">rand</h3><p>The following function generates a random positive integer.</p><pre><code>defn rand () -> Int</code></pre><p>The following function generates a random positive integer that is guaranteed to be strictly less than n.</p><pre><code>defn rand (n:Int) -> Int</code></pre><p>The following function generates a random positive integer within the range specified by <code>r</code>. <code>r</code> must have a step size of one.</p><pre><code>defn rand (r:Range) -> Int</code></pre><h3 id="anchor328">ceil-log2</h3><p><code>ceil-log2</code> computes the ceiling of the base-2 logarithm of the integer <code>i</code>.</p><pre><code>defn ceil-log2 (i:Int) -> Int<br>defn ceil-log2 (i:Long) -> Int</code></pre><h3 id="anchor329">floor-log2</h3><p><code>floor-log2</code> computes the floor of the base-2 logarithm of the integer <code>i</code>.</p><pre><code>defn floor-log2 (i:Int) -> Int<br>defn floor-log2 (i:Long) -> Long</code></pre><h3 id="anchor330">next-pow2</h3><p><code>next-pow2</code> computes the smallest power of <code>2</code> that is greater than or equal to the given integer <code>i</code>. <code>i</code> cannot be negative.</p><pre><code>defn next-pow2 (i:Int) -> Int<br>defn next-pow2 (i:Long) -> Long</code></pre><h3 id="anchor331">prev-pow2</h3><p><code>prev-pow2</code> computes the largest power of <code>2</code> that is smaller than or equal to the given integer <code>i</code>. <code>i</code> cannot be negative.</p><pre><code>defn prev-pow2 (i:Int) -> Int<br>defn prev-pow2 (i:Long) -> Long</code></pre><h3 id="anchor332">sum</h3><p><code>sum</code> computes the sum of the given sequence of numbers.</p><pre><code>defn sum (xs:Seqable<Int>) -> Int<br>defn sum (xs:Seqable<Long>) -> Long<br>defn sum (xs:Seqable<Float>) -> Float<br>defn sum (xs:Seqable<Double>) -> Double</code></pre><h3 id="anchor333">product</h3><p><code>product</code> computes the product of the given sequence of numbers.</p><pre><code>defn product (xs:Seqable<Int>) -> Int<br>defn product (xs:Seqable<Long>) -> Long<br>defn product (xs:Seqable<Float>) -> Float<br>defn product (xs:Seqable<Double>) -> Double</code></pre><h2 id="anchor334">Boolean Types</h2><p>Boolean values are represented using the types <code>True</code> and <code>False</code>.</p><pre><code>deftype True <: Equalable<br>deftype False <: Equalable</code></pre><p>Both <code>True</code> and <code>False</code> are subtypes of <code>Equalable</code> and hence support the <code>equal?</code> operation. Values of type <code>True</code> are only equal to other values of type <code>True</code>. Values of type <code>False</code> are only equal to other values of type <code>False</code>.</p><h3 id="anchor335">complement</h3><p><code>complement</code> returns the logical complement of its argument. If <code>a</code> is true, then it returns <code>false</code>, otherwise it returns <code>true</code>.</p><pre><code>defn complement (a:True|False) -> True|False</code></pre><h2 id="anchor336">Character Type</h2> <p>A <code>Char</code> represents a single byte ascii character.</p><pre><code>deftype Char <: Equalable & Hashable & Comparable<Char></code></pre><p><code>Char</code> is defined to be a subtype of <code>Equalable</code>, <code>Hashable</code>, and <code>Comparable</code>, and thus it supports the equality operator, the <code>hash</code> multi, and can be compared other values of type <code>Char</code>.</p><p>Two values of type <code>Char</code> are compared according to the numerical value of their ascii encoding.</p><h3 id="anchor337">digit?</h3><p><code>digit?</code> checks whether a given character is a digit character, representing one of the numerals between <code>0</code> and <code>9</code>.</p><pre><code>defn digit? (c:Char) -> True|False</code></pre><h3 id="anchor338">letter?</h3><p><code>letter?</code> checks whether a given character is either a lower or upper-case character, representing one of the letters between <code>'A'</code> and <code>'Z'</code> or between <code>'a'</code> and <code>'z'</code>.</p><pre><code>defn letter? (c:Char) -> True|False</code></pre><h3 id="anchor339">upper-case?</h3><p><code>upper-case?</code> checks whether a given character is an upper-case character, representing one of the letters between <code>'A'</code> and <code>'Z'</code>.</p><pre><code>defn upper-case? (c:Char) -> True|False</code></pre><h3 id="anchor340">lower-case?</h3><p><code>lower-case?</code> checks whether a given character is a lower-case character, representing one of the letters between <code>'a'</code> and <code>'z'</code>.</p><pre><code>defn lower-case? (c:Char) -> True|False</code></pre><h3 id="anchor341">lower-case</h3><p><code>lower-case</code> converts a given character to its lower-case representation if it is a letter, otherwise returns the original character.</p><pre><code>defn lower-case (c:Char) -> Char</code></pre><h3 id="anchor342">upper-case</h3><p><code>upper-case</code> converts a given character to its upper-case representation if it is a letter, otherwise returns the original character.</p><pre><code>defn upper-case (c:Char) -> Char</code></pre><h2 id="anchor343">Range</h2><p>A <code>Range</code> represents a span of integers between a starting index and an optional ending index. </p><pre><code>deftype Range <: Collection<Int> & Equalable </code></pre><h3 id="anchor344">Range</h3><p>The following function creates a range with a given starting index, an optional ending index, a step size, and a flag indicating whether the ending index is inclusive or exclusive.</p><pre><code>defn Range (start:Int, end:Int|False, step:Int, inclusive?:True|False) -> Range</code></pre><p>Users will typically use one of the macro forms for creating a range. The following form creates a range with the starting index <code>a</code>, exclusive ending index <code>b</code>, and step size <code>1</code>.</p><pre><code>a to b </code></pre><p>The keyword <code>by</code> can be used to provide a custom step size.</p><pre><code>a to b by n</code></pre><p>To create ranges with inclusive ending indices, use the keyword <code>through</code> instead of <code>to</code>.</p><pre><code>a through b<br>a through b by n</code></pre><p><code>Range</code> is a subtype of <code>Collection</code> and implements an appropriate method for the <code>to-seq</code> multi. A range is viewed as a sequence of numbers starting from its given starting index, and proceeding until its ending index by the given step size. If the ending index is inclusive, then the sequence may contain the ending index. If the ending index is exclusive, then the sequence will not contain the ending index. If no ending index is given, then the sequence is infinite.</p><p><code>Range</code> is a subtype of <code>Equalable</code> and two ranges are defined to be equal if they have equivalent starting and ending indices, step sizes, and inclusion flags.</p><h3 id="anchor345">Dense Index Ranges</h3><p>For many of the core library functions, ranges are used to specify bounds within a <code>Lengthable</code> collection. For these ranges, the range argument must be a <span style="font-style:italic;">dense index range</span> with respect to the given collection. A range is a <span style="font-style:italic;">dense index range</span> with respect to a collection if it satisfies the following restrictions:</p><ol><li>The step size of the range must be 1.
</li><li>If the range is infinite, then the starting index must be non-negative and less than or equal to the length of the collection.
</li><li>If the range is finite and inclusive, then the starting and ending indices must be non-negative and less than the length of the collection. The starting index must be less than or equal to the ending index.
</li><li>If the range is finite and exclusive, then the starting and ending indices must be non-negative and less than or equal to the length of the collection. The starting index must be less than or equal to the ending index.
</li></ol><h3 id="anchor346">start</h3><p><code>start</code> returns the starting index of the given range.</p><pre><code>defn start (r:Range) -> Int</code></pre><h3 id="anchor347">end</h3><p><code>end</code> returns the ending index of the given range if there is one, or <code>false</code> otherwise.</p><pre><code>defn end (r:Range) -> Int</code></pre><h3 id="anchor348">step</h3><p><code>step</code> returns the step size of the given range.</p><pre><code>defn step (r:Range) -> Int</code></pre><h3 id="anchor349">inclusive?</h3><p><code>inclusive?</code> returns <code>true</code> if the ending index of the given range is inclusive, or <code>false</code> otherwise.</p><pre><code>defn inclusive? (r:Range) -> True|False</code></pre><h3 id="anchor350">map</h3><p><code>map</code> returns a list containing the result of applying the function <code>f</code> to each integer within the given range. It is a fatal error to call <code>map</code> on a range with infinite length.</p><pre><code>defn map<?R> (f: Int -> ?R, r:Range) -> List<R></code></pre><h2 id="anchor351">String</h2><p>A <code>String</code> represents an immutable collection of values of type <code>Char</code>.</p><pre><code>deftype String <: Lengthable &<br> Collection<Char> &<br> Equalable &<br> Hashable &<br> Comparable<String></code></pre><p><code>String</code> is a subtype of <code>Equalable</code> and hence supports the <code>equal?</code> operation. Two strings are equal if they have the same length and all of their characters are respectively equal.</p><p><code>String</code> is a subtype of <code>Lengthable</code> and hence supports the <code>length</code> operation.</p><p><code>String</code> is a subtype of <code>Hashable</code>, hence supports the <code>hash</code> operation and can be used as keys in a <code>HashTable</code>.</p><p><code>String</code> is a subtype of <code>Comparable</code>, and two values of type <code>String</code> can be compared using the standard comparison operations according to their lexicographic ordering.</p><p><code>String</code> is a subtype of <code>Collection</code>, and supports the <code>to-seq</code> operation for viewiewing the <code>String</code> as a sequence of values of type <code>Char</code>.</p><h3 id="anchor352">String</h3><p>The following function creates a new <code>String</code> containing <code>n</code> copies of the <code>c</code> character.</p><pre><code>defn String (n:Int, c:Char) -> String</code></pre><p>The following function converts the given sequence of characters into a <code>String</code>.</p><pre><code>defn String (cs:Seqable<Char>) -> String</code></pre><h3 id="anchor353">get</h3><p><code>get</code> allows for retrieval of individual characters in a <code>String</code> by index. It is a fatal error to provide an index that is beyond the bounds of the string.</p><pre><code>defn get (s:String, i:Int) -> Char</code></pre><h3 id="anchor354">get</h3><p><code>get</code> allows for retrieval of a range of characters in a <code>String</code>. The given range must be a <span style="font-style:italic;">dense index range</span> with respect to the given string.</p><pre><code>defn get (s:String, r:Range) -> String</code></pre><p>For example, assuming that <code>s</code> contains the string <code>"Hello World"</code>, here is what various calls to <code>get</code> will return:</p><pre><code>s[1 to 4] returns "ell"<br>s[1 through 4] returns "ello"<br>s[1 to false] returns "ello World"</code></pre><h3 id="anchor355">Parsing Numbers</h3><p>The following functions convert the string representations of numbers to their numerical types.</p><pre><code>defn to-byte (s:String) -> False|Byte<br>defn to-int (s:String) -> False|Int<br>defn to-long (s:String) -> False|Long<br>defn to-float (s:String) -> False|Float<br>defn to-double (s:String) -> False|Double</code></pre><p>Each of the above functions returns <code>false</code> if the given string cannot be converted to the appropriate type, either because of an incorrectly formatted string, or because the resulting number cannot be represented using the appropriate number of bits.</p><h3 id="anchor356">to-string</h3><p>The following multi converts a given object to its string representation.</p><pre><code>defmulti to-string (x) -> String</code></pre><p>A default method defined in terms of <code>print</code> is provided to convert arbitrary objects to their string representation. User defined types are advised to rely upon this default method and <span style="font-style:italic;">not</span> provide their own method for <code>to-string</code>. To provide custom printing behaviour for a type, users should provide methods for <code>print</code> instead. </p><h3 id="anchor357">String Interpolation</h3><p>The <code>modulo</code> operator creates a printable object given a format string and a sequence of arguments.</p><pre><code>defn modulo (format:String, args:Seqable) -> Printable</code></pre><p>The characters in the format string are printed one by one, where occurrences of a splicing operator prints the next item in the sequence. The available splicing operators are:</p><ol><li> <code>%_</code> : Prints the next item in the sequence.
</li><li> <code>%*</code> : Assumes the next item in the sequence is <code>Seqable</code>, and prints all elements in the item.
</li><li> <code>%,</code> : Assumes the next item in the sequence is <code>Seqable</code>, and prints all elements in the item separated by commas.
</li><li> <code>%~</code> : Pretty prints the next item in the sequence using the <code>write</code> function.
</li><li> <code>%@</code> : Assumes the next item in sequence is <code>Seqable</code>, and pretty prints all elements in the item separated by spaces.
</li><li> <code>%%</code> : Prints the percentage sign character.
</li></ol><p>For example, the following command will print <code>"On Tuesdays, Thursdays, Wednesdays, Patrick goes for a walk."</code>.</p><pre><code>val days = ["Tuesdays", "Thursdays", "Wednesdays"]<br>val name = "Patrick"<br>val activity = "walk"<br>println("On %,, %_ goes for a %_." % [days, name, activity])</code></pre><p>Note that the <code>modulo</code> function does <span style="font-style:italic;">not</span> return a <code>String</code>. The <code>to-string</code> function may be used to convert the printable object into a string.</p><pre><code>val days = ["Tuesdays", "Thursdays", "Wednesdays"]<br>val name = "Patrick"<br>val activity = "walk"<br>to-string("On %,, %_ goes for a %_." % [days, name, activity])</code></pre><h3 id="anchor358">matches?</h3><p><code>matches?</code> returns <code>true</code> if the string <code>b</code> can be found at position <code>start</code> in the string <code>a</code>, or <code>false</code> otherwise.</p><pre><code>defn matches? (a:String, start:Int, b:String) -> True|False</code></pre><h3 id="anchor359">prefix?</h3><p><code>prefix?</code> returns <code>true</code> if the string <code>a</code> starts with the given <code>prefix</code>, or <code>false</code> otherwise.</p><pre><code>defn prefix? (s:String, prefix:String) -> True|False</code></pre><h3 id="anchor360">suffix?</h3><p><code>suffix?</code> returns <code>true</code> if the string <code>a</code> ends with the given suffix, or <code>false</code> otherwise.</p><pre><code>defn suffix? (s:String, suffix:String) -> True|False</code></pre><h3 id="anchor361">empty?</h3><p><code>empty?</code> returns <code>true</code> if the string contains no characters.</p><pre><code>defn empty? (s:String) -> True|False</code></pre><h3 id="anchor362">append</h3><p><code>append</code> returns a new string resulting from concatenating string <code>b</code> to the end of string <code>a</code>.</p><pre><code>defn append (a:String, b:String) -> String</code></pre><h3 id="anchor363">append-all</h3><p><code>append-all</code> returns a new string resulting from concatenating together all strings in a sequence.</p><pre><code>defn append-all (xs:Seqable<String>) -> String</code></pre><h3 id="anchor364">string-join</h3><p><code>string-join</code> returns the string resulting from printing out each item in the sequence <code>xs</code>. If the argument <code>j</code> is given, then each item in the sequence is separated by <code>j</code>.</p><pre><code>defn string-join (xs:Seqable) -> String<br>defn string-join (xs:Seqable, j) -> String</code></pre><h3 id="anchor365">index-of-char</h3><p><code>index-of-char</code> searches the string <code>s</code>, within the bounds indicated the range <code>r</code>, for the first occurrence of the character <code>c</code>. If <code>c</code> is found, then its index is returned, otherwise <code>false</code> is returned. If a range is not given, then by default the function searches through the entire string. The given range must be a <span style="font-style:italic;">dense index range</span> with respect to the string.</p><pre><code>defn index-of-char (s:String, r:Range, c:Char) -> False|Int<br>defn index-of-char (s:String, c:Char) -> False|Int</code></pre><h3 id="anchor366">index-of-chars</h3><p><code>index-of-chars</code> searches the string <code>s</code>, within the bounds indicated by the range <code>r</code>, for the first occurrence of the substring <code>b</code>. If it is found, then its index is returned, otherwise <code>false</code> is returned. If a range is not given, then by default the function searches through the entire string. The given range must be a <span style="font-style:italic;">dense index range</span> with respect to the string.</p><pre><code>defn index-of-chars (s:String, r:Range, b:String) -> False|Int<br>defn index-of-chars (s:String, b:String) -> False|Int</code></pre><h3 id="anchor367">last-index-of-char</h3><p><code>last-index-of-char</code> searches the string <code>s</code>, within the bounds indicated the range <code>r</code>, for the last occurrence of the character <code>c</code>. If <code>c</code> is found, then its index is returned, otherwise <code>false</code> is returned. If a range is not given, then by default the function searches through the entire string. The given range must be a <span style="font-style:italic;">dense index range</span> with respect to the string.</p><pre><code>defn last-index-of-char (s:String, r:Range, c:Char) -> False|Int<br>defn last-index-of-char (s:String, c:Char) -> False|Int</code></pre><h3 id="anchor368">last-index-of-chars</h3><p><code>last-index-of-chars</code> searches the string <code>s</code>, within the bounds indicated by the range <code>r</code>, for the last occurrence of the substring <code>b</code>. If it is found, then its index is returned, otherwise <code>false</code> is returned. If a range is not given, then by default the function searches through the entire string. The given range must be a <span style="font-style:italic;">dense index range</span> with respect to the string.</p><pre><code>defn last-index-of-chars (s:String, r:Range, b:String) -> False|Int<br>defn last-index-of-chars (s:String, b:String) -> False|Int</code></pre><h3 id="anchor369">replace</h3><p><code>replace</code> returns the result of replacing every occurrence of the character <code>c1</code> in the string <code>s</code> with the character <code>c2</code>.</p><pre><code>defn replace (s:String, c1:Char, c2:Char) -> String</code></pre><h3 id="anchor370">replace</h3><p><code>replace</code> returns the result of replacing every occurrence of the substring <code>s1</code> in the string <code>str</code> with the substring <code>s2</code>.</p><pre><code>defn replace (str:String, s1:String, s2:String) -> String</code></pre><h3 id="anchor371">split</h3><p><code>split</code> returns a lazily computed sequence resulting from splitting the string <code>str</code> at occurrences of the substring <code>s</code>. If the argument <code>n</code> is given, then the resulting sequence is restricted to contain at most <code>n</code> strings, where the last string contains the unsplit remainder of <code>str</code>.</p><pre><code>defn split (str:String, s:String) -> Seq<String> <br>defn split (str:String, s:String, n:Int) -> Seq<String></code></pre><p>The following relation is guaranteed return <code>true</code>.</p><pre><code>string-join(split(str, s), s) == str</code></pre><h3 id="anchor372">lower-case</h3><p><code>lower-case</code> the result of converting all letters contained within the string <code>s</code> to lower-case.</p><pre><code>defn lower-case (s:String) -> String</code></pre><h3 id="anchor373">upper-case</h3><p><code>upper-case</code> the result of converting all letters contained within the string <code>s</code> to upper-case.</p><pre><code>defn upper-case (s:String) -> String</code></pre><h3 id="anchor374">trim</h3><p><code>trim</code> returns the result of removing all leading and trailing characters that satisfy the function <code>pred</code> from the string <code>s</code>.</p><pre><code>defn trim (pred: Char -> True|False, s:String) -> String</code></pre><p>If <code>pred</code> is not given, then <code>trim</code>, by default, removes all leading and trailing whitespace characters.</p><h2 id="anchor375">StringBuffer</h2><p>A <code>StringBuffer</code> is an extendable array for holding characters.</p><pre><code>deftype StringBuffer <: IndexedCollection<Char> & OutputStream </code></pre><p><code>StringBuffer</code> is a subtype of a <code>IndexedCollection</code> and implements appropriate methods for retrieving its length, and getting and setting characters by index.</p><p>When setting a character at an index <code>i</code>, if <code>i</code> is less than the length of the buffer, then the character currently at index <code>i</code> will be overwritten. If <code>i</code> is equal to the length of the buffer, then <code>i</code> will be added to the end of the buffer, and the buffer's length will increase by 1.</p><p><code>StringBuffer</code> is a subtype of <code>OutputStream</code> and can be used as a target for the <code>print</code> function.</p><h3 id="anchor376">StringBuffer</h3><p>This function creates a <code>StringBuffer</code> with the initial capacity <code>n</code>. The capacity of a StringBuffer is the number of characters it may hold before it undergoes resizing.</p><pre><code>defn StringBuffer (n:Int) -> StringBuffer</code></pre><p>If no capacity is provided, then the default capacity is <code>32</code>.</p><pre><code>defn StringBuffer () -> StringBuffer </code></pre><h3 id="anchor377">add</h3><p>This function will add the character <code>c</code> to the end of the buffer.</p><pre><code>defn add (s:StringBuffer, c:Char) -> False</code></pre><h3 id="anchor378">add-all</h3><p>This function will add all the characters in the sequence <code>cs</code> to the end of the buffer.</p><pre><code>defn add-all (s:StringBuffer, cs:Seqable<Char>) -> False</code></pre><h3 id="anchor379">clear</h3><p>This function will clear all characters in the <code>StringBuffer</code>.</p><pre><code>defn clear (s:StringBuffer) -> False</code></pre><h2 id="anchor380">Array</h2><p>Arrays are the most fundamental <code>IndexedCollection</code> in Stanza, representing a finite series of items with constant time access to elements by index.</p><pre><code>deftype Array<T> <: IndexedCollection<T> & Equalable</code></pre><p><code>Array</code> is a subtype of <code>IndexedCollection</code> and hence supports the fundamental <code>get</code>, <code>set</code>, and <code>length</code> operations.</p><p><code>Array</code> is a subtype of <code>Equalable</code> and two arrays are defined to be equal only if they are the same array.</p><h3 id="anchor381">Array</h3><p>This function creates an <code>Array</code> with length <code>n</code> for holding values of type <code>T</code>. It is a fatal error to read from an index that has not been initialized, and <code>n</code> cannot be negative.</p><pre><code>defn Array<T> (n:Int) -> Array<T></code></pre><p>This function creates an <code>Array</code> with length <code>n</code> for holding values of type <code>T</code> with each index initialized to the item <code>x</code>. <code>n</code> cannot be negative.</p><pre><code>defn Array<T> (n:Int, x:T) -> Array<T></code></pre><h3 id="anchor382">to-array</h3><p>This function converts a sequence of items of type <code>T</code> to an array.</p><pre><code>defn to-array<T> (xs:Seqable<T>) -> Array<T></code></pre><h3 id="anchor383">map</h3><p>This function creates a new array where each item is initialized to the result of calling the function <code>f</code> on each item in the given array <code>xs</code>. Note that the element type of the result array, <code>R</code>, must be provided explicitly.</p><pre><code>defn map<R,?T> (f:T -> R, xs:Array<?T>) -> Array<R></code></pre><h2 id="anchor384">CharArray</h2><p><code>CharArray</code> objects are specialized arrays designed specifically for efficiently storing <code>Char</code> objects.</p><pre><code>deftype CharArray <: Array<Char></code></pre><p><code>CharArray</code> objects behave equivalently to <code>Array<Char></code> objects.</p><h3 id="anchor385">CharArray</h3><p>This function creates a <code>CharArray</code> of length <code>n</code>, with each index initialized to the space character.</p><pre><code>defn CharArray (n:Int) -> CharArray</code></pre><p>This function creates a <code>CharArray</code> of length <code>n</code>, with each index initialized to the given character <code>x</code>.</p><pre><code>defn CharArray (n:Int, x:Char) -> CharArray</code></pre><h3 id="anchor386">get-chars</h3><p>This function allows for efficient retrieval of characters from a <code>CharArray</code>. The range <code>r</code> must be a <span style="font-style:italic;">dense index range</span> with respect to <code>cs</code>.</p><pre><code>defn get-chars (cs:CharArray, r:Range) -> String</code></pre><h3 id="anchor387">set-chars</h3><p>This function allows for efficient assignment of characters in a <code>CharArray</code>. The range <code>r</code> must be a <span style="font-style:italic;">dense index range</span> with respect to <code>cs</code>.</p><pre><code>defn set-chars (cs:CharArray, r:Range, s:String) -> False</code></pre><h2 id="anchor388">ByteArray</h2><p><code>ByteArray</code> objects are specialized arrays designed specifically for efficiently storing <code>Byte</code> objects.</p><pre><code>deftype ByteArray <: Array<Byte></code></pre><p><code>ByteArray</code> objects behave equivalently to <code>Array<Byte></code> objects.</p><h3 id="anchor389">ByteArray</h3><p>This function creates a <code>ByteArray</code> of length <code>n</code>, with each index initialized to <code>0Y</code>.</p><pre><code>defn ByteArray (n:Int) -> ByteArray</code></pre><p>This function creates a <code>ByteArray</code> of length <code>n</code>, with each index initialized to the given byte <code>x</code>.</p><pre><code>defn ByteArray (n:Int, x:Byte) -> ByteArray</code></pre><h2 id="anchor390">Tuple</h2><p>A <code>Tuple</code> represents a finite and immutable series of items each with an integer index.</p><pre><code>deftype Tuple<T> <: Lengthable &<br> Collection<T> &<br> Equalable &<br> Hashable &<br> Comparable<Tuple<T>></code></pre><p><code>Tuple</code> is a subtype of <code>Equalable</code> and two tuples are defined to be equal if they have the same length and all of their components are equal. It is an error to check whether two tuples are equal if they contain elements that are not <code>Equalable</code>.</p><p><code>Tuple</code> is a subtype of <code>Collection</code> and implements an appropriate method for the <code>to-seq</code> multi to access the elements of the tuple as a sequence.</p><p><code>Tuple</code> is a subtype of <code>Hashable</code> and computes its hash by combining the hashes of all of its items. It is a fatal error to call <code>hash</code> on a tuple containing items that are not <code>Hashable</code>.</p><p><code>Tuple</code> is a subtype of <code>Comparable</code> and implements an appropriate method for the <code>compare</code> multi that compares two tuples by their lexicographic order. It is a fatal error to compare two tuples containing elements that are not <code>Comparable</code> with each other.</p><p><code>Tuple</code> is a subtype of <code>Lengthable</code> and its length can be queried by calling the <code>length</code> multi.</p><h3 id="anchor391">Tuple</h3><p><code>Tuple</code> creates a tuple of length <code>n</code> with each element initialized to <code>x</code>.</p><pre><code>defn Tuple<?T> (n:Int, x:?T) -> Tuple<T> </code></pre><h3 id="anchor392">to-tuple</h3><p><code>to-tuple</code> converts a finite sequence of items into a tuple. The function will not terminate if given an infinite sequence.</p><pre><code>defn to-tuple<?T> (xs:Seqable<?T>) -> Tuple<T></code></pre><h3 id="anchor393">get</h3><p><code>get</code> will return the item at index <code>i</code> within the tuple <code>x</code>. <code>i</code> must be within the bounds of the range.</p><pre><code>defn get<?T> (x:Tuple<?T>, i:Int) -> T</code></pre><h3 id="anchor394">get</h3><p><code>get</code> will return a new <code>Tuple</code> containing the items spanned by the given range. The range must be a <span style="font-style:italic;">dense index range</span> with respect to the tuple. </p><pre><code>defn get<?T> (xs:Tuple<?T>, r:Range) -> Tuple<T></code></pre><h3 id="anchor395">map</h3><p><code>map</code> returns a new tuple containing the result of calling the function <code>f</code> on each item in the tuple <code>xs</code>.</p><pre><code>defn map<?T,?R> (f:T -> ?R, xs:Tuple<?T>) -> Tuple<R></code></pre><h3 id="anchor396">empty?</h3><p><code>empty?</code> returns <code>true</code> if the tuple <code>t</code> is empty, otherwise it returns <code>false</code>.</p><pre><code>defn empty? (t:Tuple) -> True|False</code></pre><h2 id="anchor397">List</h2><p>A List represents an immutable linked list of items.</p><pre><code>deftype List<T> <: Lengthable &<br> Collection<T> &<br> Equalable &<br> Hashable &<br> Comparable<List<T>> </code></pre><p><code>List</code> is a subtype of <code>Lengthable</code> and its length can be queried by calling the <code>length</code> multi. Note that the length of a list is not cached, and computing the length of a list takes time proportional to the length of the list.</p><p><code>List</code> is a subtype of <code>Collection</code> and implements an appropriate method for the <code>to-seq</code> multi for viewing the list as a sequence.</p><p><code>List</code> is a subtype of <code>Equalable</code> and two lists are defined to be equal if they have the same length and all of their components are equal. It is a fatal error to check whether two lists are equal if they contain elements that are not <code>Equalable</code>.</p><p><code>List</code> is a subtype of <code>Hashable</code> and implements an appropriate method for the <code>hash</code> multi. The hash is computed by combining the hashes of all the items in the list. It is a fatal error to call hash on a list containing elements that are not <code>Hashable</code>.</p><p><code>List</code> is a subtype of <code>Comparable</code> and implements an appropriate method for the <code>compare</code> multi. Two lists are compared according to their lexicographic ordering. It is a fatal error to compare two lists that contain elements that are not <code>Comparable</code> to each other.</p><h3 id="anchor398">List</h3><p>The following functions create lists with no, one, two, three, or four elements respectively. The <code>to-list</code> function can be used to create lists with more than four elements.</p><pre><code>defn List () -> List<Void><br>defn List<?T> (x:?T) -> List<T><br>defn List<?T> (x:?T, y:?T) -> List<T><br>defn List<?T> (x:?T, y:?T, z:?T) -> List<T><br>defn List<?T> (w:?T, x:?T, y:?T, z:?T) -> List<T></code></pre><h3 id="anchor399">cons</h3><p><code>cons</code> (short for "construct") creates new lists by appending one, two, or three elements to the head of an existing list. The <code>append</code> function can be used to append more than three elements to a list.</p><pre><code>defn cons<?T> (x:?T, t:List<?T>) -> List<T><br>defn cons<?T> (x:?T, y:?T, t:List<?T>) -> List<T><br>defn cons<?T> (x:?T, y:?T, z:?T, t:List<?T>) -> List<T></code></pre><h3 id="anchor400">to-list</h3><p><code>to-list</code> creates a new list containing the items in the sequence <code>xs</code>. The function will not terminate if given an infinite sequence.</p><pre><code>defn to-list<?T> (xs:Seqable<?T>) -> List<T></code></pre><h3 id="anchor401">head</h3><p><code>head</code> returns the head of a list. It is a fatal error to call <code>head</code> on an empty list.</p><pre><code>defmulti head<?T> (x:List<?T>) -> T</code></pre><h3 id="anchor402">tail</h3><p><code>tail</code> returns the tail of a list. It is a fatal error to call <code>tail</code> on an empty list.</p><pre><code>defmulti tail<?T> (x:List<?T>) -> List<T></code></pre><h3 id="anchor403">empty?</h3><p><code>empty?</code> returns <code>true</code> if the given list is empty or <code>false</code> otherwise.</p><pre><code>defmulti empty? (x:List) -> True|False</code></pre><h3 id="anchor404">get</h3><p><code>get</code> returns the <code>i</code>'th element in the list <code>xs</code>. <code>i</code> must be within the bounds of <code>xs</code>.</p><pre><code>defn get<?T> (xs:List<?T>, i:Int) -> T</code></pre><h3 id="anchor405">headn</h3><p><code>headn</code> returns a list containing the <code>n</code> first elements in the list <code>l</code>. <code>n</code> must be less than or equal to the length of the list.</p><pre><code>defn headn<?T> (l:List<?T>, n:Int) -> List<T></code></pre><h3 id="anchor406">tailn</h3><p><code>tailn</code> returns the list after removing the first <code>n</code> elements from the head of the list <code>l</code>. <code>n</code> must be less than or equal to the length of the list.</p><pre><code>defn tailn<?T> (l:List<?T>, n:Int) -> List<T></code></pre><h3 id="anchor407">reverse</h3><p><code>reverse</code> returns a new list containing the items in <code>xs</code> in reversed order.</p><pre><code>defn reverse<?T> (xs:List<?T>) -> List<T></code></pre><h3 id="anchor408">in-reverse</h3><p><code>in-reverse</code> returns a sequence containing the items in the list in reverse order.</p><pre><code>defn in-reverse<?T> (xs:List<?T>) -> Seq<T></code></pre><h3 id="anchor409">last</h3><p><code>last</code> returns the last element in the list. The list must not be empty.</p><pre><code>defn last<?T> (xs:List<?T>) -> T</code></pre><h3 id="anchor410">but-last</h3><p><code>but-last</code> returns a list containing all elements in <code>xs</code> except the last. <code>xs</code> must not be empty.</p><pre><code>defn but-last<?T> (xs:List<?T>) -> List<T></code></pre><h3 id="anchor411">append</h3><p><code>append</code> returns the list resulting from appending all items from <code>xs</code> to the beginning of the list <code>ys</code>.</p><pre><code>defn append<?T> (xs:Seqable<?T>, ys:List<?T>) -> List<T></code></pre><h3 id="anchor412">append-all</h3><p><code>append-all</code> returns the list resulting from appending together all lists in the sequence <code>xs</code>.</p><pre><code>defn append-all<?T> (xs:Seqable<List<?T>>) -> List<T></code></pre><h3 id="anchor413">transpose</h3><p><code>transpose</code> returns a transposed version of the input list <code>xs</code>. The first element in the result list is a list containing the first elements in each list within <code>xs</code>. The second element in the result list is a list containing the second elements in each list within <code>xs</code>. The third element in the result list is a list containing the third elements in each list within <code>xs</code>, et cetera. The result list has the same length as the shortest list within xs.</p><pre><code>defn transpose<?T> (xs:List<List<?T>>) -> List<List<T>></code></pre><h3 id="anchor414">map</h3><p><code>map</code> returns a new list consisting of the results of applying the function <code>f</code> to each element in the input list <code>xs</code>.</p><pre><code>defn map<?T,?R> (f: T -> ?R, xs:List<?T>) -> List<R></code></pre><h3 id="anchor415">map</h3><p>The following functions returns a new list consisting of the results of applying the function <code>f</code> to each pair (or triplet) of elements in the given input lists (or sequences). The result list has the same length as the shortest input list or sequence.</p><pre><code>defn map<?T,?S,?R> (f: (T,S) -> ?R,<br> xs:List<?T>,<br> ys:Seqable<?S>) -> List<R><br> <br>defn map<?T,?S,?U,?R> (f: (T,S,U) -> ?R,<br> xs:List<?T>,<br> ys:Seqable<?S>,<br> zs:Seqable<?U>) -> List<R></code></pre><h3 id="anchor416">seq-append</h3><p><code>seq-append</code> returns a new list by calling the function <code>f</code> on every item in the sequence <code>xs</code>, and then appending together all of the resultant lists.</p><pre><code>defn seq-append<?T,?R> (f: T -> List<?R>, xs:Seqable<?T>) -> List<R></code></pre><h3 id="anchor417">seq-append</h3><p>The following functions returns a new list by calling the function <code>f</code> on each pair (or triplet) of items in the input sequences, and then appending together all of the resultant lists.</p><pre><code>defn seq-append<?T,?S,?R> (f: (T,S) -> List<?R>,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>) -> List<R><br> <br>defn seq-append<?T,?S,?U,?R> (f: (T,S,U) -> List<?R>,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>,<br> zs:Seqable<?U>) -> List<R></code></pre><h2 id="anchor418">FileInfo</h2><p>A <code>FileInfo</code> object contains position information about a specific point in a text file.</p><pre><code>deftype FileInfo <: Equalable &<br> Hashable &<br> Comparable<FileInfo></code></pre><p><code>FileInfo</code> is a subtype of <code>Equalable</code> and two <code>FileInfo</code> objects are equal when their filenames, lines, and columns are equal.</p><p><code>FileInfo</code> is a subtype of <code>Hashable</code> and implements an appropriate method for the <code>hash</code> multi by combining the hashes of its filename, line, and column information.</p><p><code>FileInfo</code> is a subtype of <code>Comparable</code> and implements an appropriate method for the <code>compare</code> multi. Two <code>FileInfo</code> objects are compared by ordering their filenames, followed their line index, followed by their column index.</p><h3 id="anchor419">FileInfo</h3><p><code>FileInfo</code> creates a <code>FileInfo</code> from the given filename, line, and column information.</p><pre><code>defn FileInfo (f:String, l:Int, c:Int) -> FileInfo</code></pre><h3 id="anchor420">filename</h3><p><code>filename</code> retrieves the filename of the given <code>FileInfo</code> object.</p><pre><code>defn filename (i:FileInfo) -> String</code></pre><h3 id="anchor421">line</h3><p><code>line</code> retrieves the line number of the given <code>FileInfo</code> object.</p><pre><code>defn line (i:FileInfo) -> Int</code></pre><h3 id="anchor422">column</h3><p><code>column</code> retrieves the column number of the given <code>FileInfo</code> object.</p><pre><code>defn column (i:FileInfo) -> Int</code></pre><h2 id="anchor423">Token</h2><p>A <code>Token</code> represents a value that has been associated with a <code>FileInfo</code> object indicating the position from which it originated in a text file.</p><pre><code>deftype Token <: Equalable</code></pre><p>A <code>Token</code> is a subtype of <code>Equalable</code> and two tokens are considered equal if its <code>FileInfo</code> objects are equal and the wrapped values are equal. It is a fatal error to check whether two <code>Token</code> objects are equal if their wrapped values are not <code>Equalable</code>.</p><h3 id="anchor424">Token</h3><p>This function creates a <code>Token</code> from the given value and its associated <code>FileInfo</code> object.</p><pre><code>defn Token (item, info:FileInfo) -> Token</code></pre><h3 id="anchor425">item</h3><p>This function retrieves the wrapped value in a <code>Token</code> object.</p><pre><code>defn item (t:Token) -> ?</code></pre><h3 id="anchor426">info</h3><p>This function retrieves the associated FileInfo object in a <code>Token</code> object.</p><pre><code>defn info (t:Token) -> FileInfo</code></pre><h3 id="anchor427">unwrap-token</h3><p>This function returns the possibly wrapped value in a token by recursively unwrapping the value if it is a token.</p><pre><code>defn unwrap-token (t) -> ?</code></pre><h3 id="anchor428">unwrap-all</h3><p>This function recursively calls <code>unwrap-token</code> on all tokens and lists in the given value. This function is commonly used to strip away all file information from an s-expression.</p><pre><code>defn unwrap-all (t) -> ?</code></pre><h2 id="anchor429">KeyValue</h2><p>A <code>KeyValue</code> pair represents a pairing of a key object of type <code>K</code> with a value object of type <code>V</code>. It is typically used to represent entries in datastructures where values are looked up according to a given key.</p><pre><code>deftype KeyValue<K,V> </code></pre><p>Typically, users will use the following macro form for creating KeyValue pairs.</p><pre><code>k => v</code></pre><h3 id="anchor430">KeyValue</h3><p>This function creates a <code>KeyValue</code> pair from the given key and value objects.</p><pre><code>defn KeyValue<?K,?V> (k:?K, v:?V) -> KeyValue<K,V></code></pre><h3 id="anchor431">key</h3><p>This function retrieves the key object in a <code>KeyValue</code> object.</p><pre><code>defn key<?K> (kv:KeyValue<?K,?>) -> K</code></pre><h3 id="anchor432">value</h3><p>This function retrieves the value object in a <code>KeyValue</code> object.</p><pre><code>defn value<?V> (kv:KeyValue<?,?V>) -> V</code></pre><h2 id="anchor433">Symbols</h2><p><code>Symbols</code> are used to represent identifiers in s-expressions, and can be compared against each other efficiently and used as keys in hashtables.</p><pre><code>deftype Symbol <: Equalable & Hashable</code></pre><p>Symbols are divided into two categories: symbols created from strings (<code>StringSymbol</code>), and uniquely generated symbols (<code>GenSymbol</code>).</p><pre><code>deftype StringSymbol <: Symbol<br>deftype GenSymbol <: Symbol</code></pre><p><code>Symbol</code> is a subtype of <code>Equalable</code> and two symbols can be efficiently compared to see whether they are equal. Two symbols created from strings are equal if the strings they are created from are equal. Two uniquely generated symbols are equal if and only if they were created by the same call to <code>gensym</code>.</p><p><code>Symbol</code> is a subtype of <code>Hashable</code> and implements an appropriate method for the <code>hash</code> multi. For symbols constructed from strings, the hash is computed from its name. For generated symbols, the hash is computed from its id.</p><h3 id="anchor434">to-symbol</h3><p>This function constructs a symbol from the given value by converting it to a string using <code>to-string</code> and then creating a symbol from the resulting string. If <code>x</code> is already a symbol then it is returned directly.</p><pre><code>defn to-symbol (x) -> Symbol</code></pre><h3 id="anchor435">symbol-join</h3><p>This function constructs a symbol from the given sequence by converting it to a string using <code>string-join</code> and then creating a symbol from the resulting string.</p><pre><code>defn symbol-join (xs:Seqable) -> Symbol</code></pre><h3 id="anchor436">gensym</h3><p>This function generates a unique symbol given an object <code>x</code> whose string representation is used as its name. The resulting symbol is guaranteed to be equal to no other symbol currently live in the program.</p><pre><code>defn gensym (x) -> Symbol</code></pre><p>If no object <code>x</code> is provided, then the default name is the string "$gen".</p><pre><code>defn gensym () -> Symbol</code></pre><h3 id="anchor437">name</h3><p>This function retrieves the string that the symbol was constructed with.</p><pre><code>defn name (x:Symbol) -> String</code></pre><h3 id="anchor438">id</h3><p>This function retrieves the identifier associated with a generated symbol. Every generated symbol is guaranteed to be associated with a unique identifier.</p><pre><code>defn id (x:GenSymbol) -> Int</code></pre><h3 id="anchor439">qualified?</h3><p>A qualified symbol is a symbol created from a string containing a <code>'/'</code> character. In Stanza, qualified symbols are used to indicate a package qualified identifier. The following function returns <code>true</code> if the given symbol is a qualified symbol, or <code>false</code> otherwise.</p><pre><code>defn qualified? (a:Symbol) -> True|False</code></pre><h3 id="anchor440">qualifier</h3> <p>This function splits a qualified symbol into a 2 element tuple containing its qualifier and its unqualified name. If the argument is not a qualified symbol, then the qualifier is <code>false</code>.</p><pre><code>defn qualifier (a:Symbol) -> [False|Symbol, Symbol]</code></pre><h3 id="anchor441">String Representation</h3><p>Note that two unique symbols, which are not equal to each other, may still have equivalent string representations. For example, a generated symbol with the name <code>"x"</code> and the id <code>253</code> has the same string representation as the symbol created from the string <code>"x253"</code>. </p><p>A typical method of converting a list of unique symbols into a list of unique strings is the following:</p><ol><li>For <code>StringSymbol</code> objects, directly use their name as their string representation.
</li><li>For <code>GenSymbol</code> objects, choose a name that is guaranteed not to be a prefix of any <code>StringSymbol</code>, then append the name to the id of the symbol. This name is typically chosen in an application-specific manner.
</li></ol><h2 id="anchor442">Maybe</h2><p>A <code>Maybe</code> object is used to indicate the presence or absence of an object.</p><pre><code>deftype Maybe<T> <: Equalable & Comparable<Maybe<T>></code></pre><p>The <code>One</code> subtype of <code>Maybe</code> indicates the presence of an object of type <code>T</code>.</p><pre><code>deftype One<T> <: Maybe<T></code></pre><p>The <code>None</code> subtype of <code>Maybe</code> indicates the absence of an object.</p><pre><code>deftype None <: Maybe<Void></code></pre><p><code>Maybe</code> is a subtype of <code>Equalable</code>. Two <code>None</code> objects are always equal. Two <code>One</code> objects are equal if their wrapped values are equal. It is an error to check whether two <code>Maybe</code> objects are equal if they wrap over values that are not <code>Equalable</code>.</p><p><code>Maybe</code> is a subtype of <code>Comparable</code> and implements an appropriate method for the <code>compare</code> multi. <code>None</code> objects are always less than <code>One</code> objects. Two <code>One</code> objects are compared by comparing their wrapped values. It is an error to compare two <code>Maybe</code> objects if they wrap over values that are not <code>Comparable</code>.</p><h3 id="anchor443">One</h3><p>This function wraps up the value <code>x</code> in a <code>One</code> object.</p><pre><code>defn One<?T> (x:?T) -> One<T></code></pre><h3 id="anchor444">None</h3><p>This function creates a new <code>None</code> object.</p><pre><code>defn None () -> None</code></pre><h3 id="anchor445">value</h3><p>This function will retrieve the wrapped value in a <code>One</code> object.</p><pre><code>defn value<?T> (x:One<?T>) -> T</code></pre><h3 id="anchor446">value?</h3><p>This function will retrieve the wrapped value in a <code>Maybe</code> object if one exists, otherwise it returns the <code>default</code> value.</p><pre><code>defn value?<?T> (x:Maybe<?T>, default:?T) -> T</code></pre><p>If no default value is given, then the <code>default</code> value is <code>false</code>.</p><pre><code>defn value?<?T> (x:Maybe<?T>) -> T|False</code></pre><h3 id="anchor447">value!</h3><p>This function assumes that the given <code>Maybe</code> object is a <code>One</code> object and returns its wrapped value.</p><pre><code>defn value!<?T> (x:Maybe<?T>) -> T</code></pre><h3 id="anchor448">empty?</h3><p>This function returns <code>true</code> if the given <code>Maybe</code> object contains no wrapped value (i.e. it is a <code>None</code> object).</p><pre><code>defn empty? (x:Maybe) -> True|False</code></pre><h2 id="anchor449">Exception</h2><p>An <code>Exception</code> object is used to represent the conditions under which an exceptional behaviour as occurred.</p><pre><code>deftype Exception </code></pre><h3 id="anchor450">Exception</h3><p>Users are encouraged to create their own subtypes of <code>Exception</code> to represent different types of exceptional behaviour. However, the following function may be used to create a generic <code>Exception</code> object with the given error message.</p><pre><code>defn Exception (msg) -> Exception</code></pre><h3 id="anchor451">throw</h3><p>This function throws the given exception object to the current exception handler. The return type of <code>Void</code> indicates that <code>throw</code> never returns.</p><pre><code>defn throw (e:Exception) -> Void</code></pre><h3 id="anchor452">with-exception-handler</h3><p>This function runs the <code>body</code> function after installing the <code>handler</code> function as the current exception handler. If the body runs without throwing an exception, then its result is returned. Otherwise the result of the exception handler is returned.</p><pre><code>defn with-exception-handler<?T> (body: () -> ?T, handler: Exception -> ?T) -> T</code></pre><h3 id="anchor453">with-finally</h3><p>This function runs the <code>body</code> function ensuring that the given <code>finally</code> function is run immediately afterwards. If the body runs to completion, then its result is returned after running the finally function. Otherwise, the finally function is run before execution exits the scope. </p><pre><code>defn with-finally<?T> (body: () -> ?T, finally: () -> ?) -> T</code></pre><h3 id="anchor454">try-catch-finally</h3><p>Users will not typically call <code>with-exception-handler</code> or <code>with-finally</code> directly and instead use the standard macro forms. The following form runs the given body with a handler for catching <code>MyException</code> objects. The code within the optional finally block is ensured to run whether or not the body runs to completion.</p><pre><code>try :<br> body code<br>catch (e:MyException) :<br> exception handling code<br>finally :<br> finalization code</code></pre><h2 id="anchor455">Fatal Errors</h2><p>A fatal error occurs when a program somehow enters an illegal state that indicates an error has occurred in the program. It is impossible for a program to recover from a fatal error, and thus fatal errors do not occur in correct programs.</p><h3 id="anchor456">fatal</h3><p>This function will print out the given error message to the screen, display a stack trace allowing users to find the source of the error, and immediately terminate the program.</p><pre><code>defn fatal (msg) -> Void</code></pre><p>On the highest (and unsafe) optimization settings, Stanza assumes that your program is correct and hence no calls to <code>fatal</code> ever occurs. For example, on the highest optimization settings, the following code:</p><pre><code>if n < 0 :<br> fatal("n should not be negative")<br>else :<br> f()</code></pre><p>is allowed to be optimized to the following:</p><pre><code>f()</code></pre><p>as Stanza assumes that your program is correct, and therefore it is impossible for execution to enter the consequent branch of the if expression.</p><h2 id="anchor457">Attempt and Failure</h2><p>The attempt and failure functions provide a convenient non-local exit for users.</p><h3 id="anchor458">fail</h3><p>The <code>fail</code> function exits from the current attempt scope and calls the current failure handler.</p><pre><code>defn fail () -> Void</code></pre><h3 id="anchor459">with-attempt</h3><p>This function calls the <code>conseq</code> function after installing the <code>alt</code> function as the current failure handler. If the <code>conseq</code> function runs to completion then its result is returned. Otherwise, if <code>fail</code> is called during execution of <code>conseq</code>, the <code>alt</code> function is called and its result is returned.</p><pre><code>defn with-attempt<?T> (conseq: () -> ?T, alt: () -> ?T) -> T</code></pre><h3 id="anchor460">attempt-else</h3><p>Users will not typically call <code>with-attempt</code> directly and instead use the standard macro forms. The following form runs the given body with a failure handler that executes when fail is called.</p><pre><code>attempt :<br> body code<br>else :<br> failure code</code></pre><p>If no <code>else</code> branch is provided, then a default <code>else</code> branch is provided that simply returns <code>false</code>.</p><h2 id="anchor461">Labeled Scopes</h2><p>Labeled scopes provide the ability to exit early from a block of code.</p><h3 id="anchor462">LabeledScope</h3><p>This function executes the <code>thunk</code> function in a new labeled scope. The <code>thunk</code> function is passed an exit function that, when called, will immediately exit <code>thunk</code>. If the <code>thunk</code> runs to completion without ever calling the exit function then its result is returned. If the exit function is called during execution of <code>thunk</code> then the argument passed to the exit function is returned.</p><pre><code>defn LabeledScope<T> (thunk: (T -> Void) -> T) -> T</code></pre><h3 id="anchor463">label</h3><p>Users will typically use the standard macro form for creating labeled scopes instead of directly calling <code>LabeledScope</code>. The following code will return the first prime number between <code>100</code> and <code>200</code>.</p><pre><code>label<Int> return :<br> for i in 100 to 200 do :<br> if prime?(i) :<br> return(i)<br> fatal("No prime found!") </code></pre><h2 id="anchor464">Generators</h2><p>Generators provide the ability to execute a function in a new coroutine and return its results in the form of a sequence. </p><h3 id="anchor465">Generator</h3><p>This function executes the <code>thunk</code> function in a new coroutine and returns a sequence. The <code>thunk</code> function is passed two functions as arguments. The first argument is the yield function, which takes a single argument. During execution of <code>thunk</code>, calls to the yield function will suspend the coroutine, and its argument will be included in the result sequence. The second argument is the <code>break</code> function, which takes either zero or one argument. During execution of <code>thunk</code>, a call to the break function with no arguments will immediately close the coroutine and end the result sequence. A call to the break function with one argument will immediately close the coroutine, include the argument as the last item in the result sequence, and then end the result sequence.</p><pre><code>defn Generator<T> (thunk : (T -> False,<br> (T -> Void)&(() -> Void)) -> ?) -> Seq<T></code></pre><h3 id="anchor466">generate</h3><p>Users will typically use the standard macro form for creating generators instead of directly calling <code>Generator</code>. The following code creates a sequence containing the first <code>100</code> prime numbers.</p><pre><code>generate<Int> :<br> var n = 0<br> for i in 2 to false do :<br> if prime?(i) :<br> n = n + 1<br> if n == 100 : break(i)<br> else : yield(i)</code></pre><h2 id="anchor467">Coroutine</h2><p>Coroutines provide the ability to execute a function in a context that can be saved and resumed later. This ability is most often used to execute a piece of code concurrently with the main program. A coroutine for which objects of type <code>I</code> are sent to its wrapped function, and for which objects of type <code>O</code> are sent back from its wrapped function is represented by the following type.</p><pre><code>deftype Coroutine<I,O> <: Equalable</code></pre><p><code>Coroutine</code> is a subtype of <code>Equalable</code>. Two coroutines are equal if they were created by the same call to <code>Coroutine</code>.</p><h3 id="anchor468">Coroutine</h3><p>This function creates a coroutine for which objects of type <code>I</code> are sent to its wrapped function, and for which objects of type <code>O</code> are sent back from its wrapped function. The argument represents the wrapped function of the coroutine.</p><pre><code>defn Coroutine<I,O> (enter: (Coroutine<I,O>, I) -> O) -> Coroutine<I,O></code></pre><p>The first argument to the wrapped function is the coroutine that is created. The second argument to the wrapped function is the argument passed in the first call to <code>resume</code> on the coroutine. The result of the function <code>enter</code> is the last value sent back from the wrapped function.</p><h3 id="anchor469">resume</h3><p>This function transfers control into a coroutine, and sends it the value <code>x</code>. The return value of <code>resume</code> is the value that is sent back by the coroutine.</p><pre><code>defn resume<?I,?O> (c:Coroutine<?I,?O>, x:I) -> O</code></pre><h3 id="anchor470">suspend</h3><p>This function transfers control out of a coroutine, and back to the main program. The value <code>x</code> is sent back to the main program. The return value of <code>suspend</code> is the value that is sent to the coroutine by the next call to <code>resume</code>.</p><pre><code>defn suspend<?I,?O> (c:Coroutine<?I,?O>, x:O) -> I</code></pre><h3 id="anchor471">break</h3><p>This function transfers control flow out of a coroutine, back to the main program, and closes the coroutine. The value <code>x</code> is sent back to the main program. <code>break</code> has no return value as the coroutine is closed and cannot be resumed afterwards.</p><pre><code>defmulti break<?O> (c:Coroutine<?,?O>, x:O) -> Void</code></pre><h3 id="anchor472">close</h3><p>This function closes a coroutine, and disallows any further calls to <code>resume</code> on the coroutine.</p><pre><code>defn close (c:Coroutine) -> False</code></pre><h3 id="anchor473">active?</h3><p>This function returns <code>true</code> if the given coroutine is currently running. Only active coroutines can be suspended or broken from.</p><pre><code>defn active? (c:Coroutine) -> True|False</code></pre><h3 id="anchor474">open?</h3><p>This function returns <code>true</code> if the given coroutine is not currently running and open to be resumed. Only open coroutines can be resumed.</p><pre><code>defn open? (c:Coroutine) -> True|False</code></pre><h2 id="anchor475">Dynamic Wind</h2><p>Consider the following code which attempts to ensure that the global variable <code>X</code> is set to the value <code>42</code> while the function <code>f</code> is running, and for <code>X</code> to be restored after <code>f</code> is done.</p><pre><code>val old-X = X<br>X = 42<br>f()<br>X = old-X</code></pre><p>However, because of coroutines it is possible for the above code to finish during the call to <code>f</code>, (for example, if <code>f</code> throws an exception) and thus leave <code>X</code> unrestored. The <code>dynamic-wind</code> function solves this problem by allowing users to perform operations upon entering or leaving a scope.</p><h3 id="anchor476">dynamic-wind</h3><p><code>dynamic-wind</code> takes a <code>body</code> function accompanied by an optional entering function, <code>in</code>, and an exiting function, <code>out</code>. <code>dynamic-wind</code> performs a call to <code>body</code> while ensuring that <code>in</code> is called every time execution enters the scope of <code>body</code>, and that <code>out</code> is called every time execution exits the scope of <code>body</code>. </p><pre><code>defn dynamic-wind<?T> (in:False|(() -> ?),<br> body:() -> ?T,<br> out:False|(() -> ?)) -> T</code></pre><p>Using <code>dynamic-wind</code>, the above example can be rewritten as follows:</p><pre><code>val old-X = X<br>dynamic-wind(<br> fn () : X = 42<br> f<br> fn () : X = old-X)</code></pre><h2 id="anchor477">Sequence Library</h2><p>The core package contains a large number of convenience functions that operate on sequences. The majority of collection datastructures in Stanza's core library are subtypes of <code>Seqable</code> and thus can be used with the sequence library.</p><h3 id="anchor478">Operating Functions</h3><p>Operating functions, such as <code>do</code>, <code>seq</code>, and <code>find</code>, are functions with type signatures compatible with the <code>for</code> macro form. The following macro form:</p><pre><code>for x in xs do :<br> body code</code></pre><p>is equivalent to the following direct call to the <code>do</code> operating function:</p><pre><code>do(fn (x) :<br> body code<br> xs)</code></pre><p>Multi-argument operating functions are used with the following macro form.</p><pre><code>for (x in xs, y in ys, z in zs) do :<br> body code</code></pre><p>is equivalent to the following direct call to the <code>do</code> operating function:</p><pre><code>do(fn (x, y, z) :<br> body code<br> xs, ys, zs) </code></pre><p>As a matter of style, if the body consists of more than a single function call then the macro form is used, as in the following example:</p><pre><code>val x = 671<br>val prime? = for i in 2 to x none? :<br> x % i == 0</code></pre><p>If the body consists of a single function call then the standard function call form is used instead.</p><pre><code>val x = 671<br>defn divides-x? (i:Int) : x % i == 0<br>val prime? = none?(divides-x?, 2 to x)</code></pre><p>The above example can also be written using anonymous function notation as follows:</p><pre><code>val x = 671<br>val prime? = none?({x % _ == 0}, 2 to x)</code></pre><h3 id="anchor479">do</h3><p>This multi calls the function <code>f</code> on each item in the sequence <code>xs</code>. A default method defined in terms of the fundamental sequence operations is provided, but users may provide customized methods for subtypes of <code>Seqable</code> for efficiency.</p><pre><code>defmulti do<?T> (f:T -> ?, xs:Seqable<?T>) -> False</code></pre><p>These multis operate similarly to the single collection version of <code>do</code> but instead calls the function <code>f</code> with successive items from multiple sequences. The sequences are stepped through in parallel and iteration stops as soon as one of them is empty.</p><pre><code>defmulti do<?T,?S> (f:(T,S) -> ?,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>) -> False<br><br>defmulti do<?T,?S,?U> (f:(T,S,U) -> ?,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>,<br> zs:Seqable<?U>) -> False</code></pre><h3 id="anchor480">find</h3><p>This function iterates through the sequence <code>xs</code> and calls the function <code>f</code> on each item, searching for the first item for which <code>f</code> returns <code>true</code>. If <code>f</code> returns <code>true</code> on some item, then that item is returned by <code>find</code>. If <code>f</code> does not return <code>true</code> on any item in the sequence, then <code>find</code> returns <code>false</code>.</p><pre><code>defn find<?T> (f: T -> True|False, xs:Seqable<?T>) -> T|False</code></pre><p>This function iterates through the sequence <code>xs</code> and <code>ys</code> in parallel and calls the function <code>f</code> with an item from each sequence. Iteration stops as soon as either sequence is empty. If <code>f</code> returns <code>true</code> when called by an item, <code>x</code>, from <code>xs</code>, and an item, <code>y</code>, from <code>ys</code>, then <code>x</code> is returned by <code>find</code>.</p><pre><code>defn find<?T,?S> (f: (T,S) -> True|False,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>) -> T|False</code></pre><h3 id="anchor481">find!</h3><p>These functions behave identically to <code>find</code> except that they assume that there exists an item (or pair of items) for which <code>f</code> returns <code>true</code>.</p><pre><code>defn find!<?T> (f: T -> True|False, xs:Seqable<?T>) -> T<br><br>defn find!<?T, ?S> (f: (T,S) -> True|False,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>) -> T</code></pre><h3 id="anchor482">first</h3><p>This function iterates through the sequence <code>xs</code> and calls the function <code>f</code> on each item, searching for the first item for which <code>f</code> returns a <code>One</code> object. If <code>f</code> returns a <code>One</code> object on some item, then the <code>One</code> object is returned. If <code>f</code> returns a <code>None</code> object for all items in the sequence, then a <code>None</code> object is returned by <code>first</code>.</p><pre><code>defn first<?T,?R> (f: T -> Maybe<?R>, xs:Seqable<?T>) -> Maybe<R></code></pre><p>This function iterates through the sequence <code>xs</code> and <code>ys</code> in parallel and calls the function <code>f</code> repeatedly with an item from each sequence. Iteration stops as soon as either sequence is empty. If <code>f</code> returns a <code>One</code> object on some pair of items, then the <code>One</code> object is returned. If <code>f</code> returns a <code>None</code> object for all items in the sequences, then a <code>None</code> object is returned by <code>first</code>.</p><pre><code>defn first<?T,?S,?R> (f: (T,S) -> Maybe<?R>,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>) -> Maybe<R></code></pre><h3 id="anchor483">first!</h3><p>These functions behave identically to <code>first</code> except that they assume that there exists an item (or pair of items) for which <code>f</code> returns a <code>One</code> object. The wrapped value within the <code>One</code> object is returned.</p><pre><code>defn first!<?T,?R> (f: T -> Maybe<?R>, xs:Seqable<?T>) -> R<br><br>defn first!<?T,?S,?R> (f: (T,S) -> Maybe<?R>,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>) -> R</code></pre><h3 id="anchor484">seq</h3><p>This function constructs the sequence resulting from calling the function <code>f</code> on each item in the sequence <code>xs</code>.</p><pre><code>defn seq<?T,?S> (f:T -> ?S, xs:Seqable<?T>) -> Seq<S></code></pre><p>These functions behave similarly to the single collection version of <code>seq</code> but instead calls the function <code>f</code> with successive items from multiple sequences. The sequences are stepped through in parallel and iteration stops as soon as one of them is empty.</p><pre><code>defn seq<?T,?S,?R> (f:(T,S) -> ?R,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>) -> Seq<R><br><br>defn seq<?T,?S,?U,?R> (f:(T,S,U) -> ?R,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>,<br> zs:Seqable<?U>) -> Seq<R></code></pre><h3 id="anchor485">seq?</h3><p>This function constructs a sequence by calling the function <code>f</code> on each item in the sequence <code>xs</code>. For each item in <code>xs</code>, if <code>f</code> returns a <code>One</code> object, then the unwrapped value is included in the result sequence. If <code>f</code> returns a <code>None</code> object then the item is not included in the result sequence.</p><pre><code>defn seq?<?T,?R> (f: T -> Maybe<?R>, xs:Seqable<?T>) -> Seq<R></code></pre><p>These functions construct a sequence by iterating through the given sequences in parallel and calling the function <code>f</code> repeatedly with an item from each sequence. For each pair (or triplet) of items, if <code>f</code> returns a <code>One</code> object, then the unwrapped value is included in the result sequence. If <code>f</code> returns a <code>None</code> object then the item is not included in the result sequence.</p><pre><code>defn seq?<?T,?S,?R> (f: (T,S) -> Maybe<?R>,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>) -> Seq<R><br> <br>defn seq?<?T,?S,?U,?R> (f: (T,S,U) -> Maybe<?R>,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>,<br> zs:Seqable<?U>) -> Seq<R></code></pre><h3 id="anchor486">filter</h3><p>This function constructs a sequence by calling the function <code>f</code> on each item in the sequence <code>xs</code>, and including the item in the result sequence only if the call to <code>f</code> returns true.</p><pre><code>defn filter<?T> (f: T -> True|False, xs:Seqable<?T>) -> Seq<T></code></pre><p>This function constructs a sequence by iterating through the <code>xs</code> and <code>ys</code> sequences in parallel and calling the function <code>f</code> repeatedly with an item from each sequence. For each pair of items, if <code>f</code> returns <code>true</code>, then the item from the <code>xs</code> sequence is included in the result sequence.</p><pre><code>defn filter<?T,?S> (f: (T,S) -> True|False,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>) -> Seq<T></code></pre><h3 id="anchor487">index-when</h3><p>This function iterates through the items in the <code>xs</code> sequence, calling <code>f</code> on each one, and returns the first index at which the call to <code>f</code> returns <code>true</code>. If no call to <code>f</code> returns <code>true</code>, then <code>index-when</code> returns <code>false</code>.</p><pre><code>defn index-when<?T> (f: T -> True|False, xs:Seqable<?T>) -> Int|False</code></pre><p>This function iterates through the <code>xs</code> and <code>ys</code> sequences in parallel, calling <code>f</code> on each pair of items from <code>xs</code> and <code>ys</code>, and returns the first index at which the call to <code>f</code> returns <code>true</code>. If no call to <code>f</code> returns <code>true</code>, then <code>index-when</code> returns <code>false</code>.</p><pre><code>defn index-when<?T,?S> (f: (T,S) -> True|False,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>) -> Int|False</code></pre><h3 id="anchor488">index-when!</h3><p>These functions behave identically to <code>index-when</code> except that they assume there exists an item (or pair of items) for which the call to <code>f</code> returns <code>true</code>.</p><pre><code>defn index-when!<?T> (f: T -> True|False, xs:Seqable<?T>) -> Int<br> <br>defn index-when!<?T,?S> (f: (T,S) -> True|False,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>) -> Int</code></pre><h3 id="anchor489">split!</h3><p>This function iterates through the items in the <code>xs</code> sequence, separating them into two collections depending on whether calling <code>f</code> on the item returns <code>true</code> or <code>false</code>. The function returns a tuple of two collections, the first of which contains all items in the sequence for which <code>f</code> returned <code>true</code>, and the second of which contains all items for which <code>f</code> returned false.</p><pre><code>defn split!<?T> (f: T -> True|False, xs:Seqable<?T>) -><br> [Collection<T>&Lengthable, Collection<T>&Lengthable]</code></pre><h3 id="anchor490">split</h3><p>This function iterates through the items in the <code>xs</code> sequence, separating them into two sequences depending on whether calling <code>f</code> on the item returns <code>true</code> or <code>false</code>. The function returns a tuple of two sequences, the first of which contains all items in the sequence for which <code>f</code> returned <code>true</code>, and the second of which contains all items for which <code>f</code> returned false. The original argument sequence should not be used after this call. </p><pre><code>defn split<?T> (f: T -> True|False, xs:Seqable<?T>) -> [Seq<T>, Seq<T>]</code></pre><h3 id="anchor491">fork</h3><p>This function takes an argument sequence and returns two other sequences containing the same items. The argument sequence is only iterated through once. The original argument sequence should not be used after this call.</p><pre><code>defn fork<?T> (xs:Seqable<?T>) -> [Seq<T>, Seq<T>]</code></pre><p>If an additional argument, <code>n</code>, is given, then the function returns <code>n</code> new sequences containing the same items. </p><pre><code>defn fork<?T> (xs:Seqable<?T>, n:Int) -> [Seq<T>, Seq<T>]</code></pre><h3 id="anchor492">take-while</h3><p>This function constructs a sequence by taking items successively from the <code>xs</code> sequence as long as calling <code>f</code> upon the item returns <code>true</code>. The resulting sequence ends as soon as <code>xs</code> is empty or <code>f</code> returns <code>false</code>. The item for which <code>f</code> returns <code>false</code> is not included in the resulting sequence.</p><pre><code>defn take-while<?T> (f: T -> True|False, xs:Seqable<?T>) -> Seq<T></code></pre><h3 id="anchor493">take-until</h3><p>This function constructs a sequence by taking items successively from the <code>xs</code> sequence as long as calling <code>f</code> upon the item returns <code>false</code>. The resulting sequence ends as soon as <code>xs</code> is empty or <code>f</code> returns <code>true</code>. The item for which <code>f</code> returns <code>true</code> is included in the resulting sequence.</p><pre><code>defn take-until<?T> (f: T -> True|False, xs:Seqable<?T>) -> Seq<T></code></pre><h3 id="anchor494">seq-cat</h3><p>This function constructs a sequence by calling <code>f</code> upon each item on the <code>xs</code> sequence. <code>seq-cat</code> then returns the concatenation of all sequences returned by <code>f</code>.</p><pre><code>defn seq-cat<?T,?R> (f:T -> Seqable<?R>, xs:Seqable<?T>) -> Seq<R></code></pre><p>These functions construct a sequence by iterating through the given sequences in parallel and calling <code>f</code> upon each pair (or triplet) of items from each sequence. <code>seq-cat</code> then returns the concatenation of all sequences returned by <code>f</code>.</p><pre><code>defn seq-cat<?T,?S,?R> (f:(T,S) -> Seqable<?R>,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>) -> Seq<R><br> <br>defn seq-cat<?T,?S,?U,?R> (f:(T,S,U) -> Seqable<?R>,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>,<br> zs:Seqable<?U>) -> Seq<R></code></pre><h3 id="anchor495">all?</h3><p>This function iterates through the items in the sequence <code>xs</code> and calls <code>pred?</code> on each one. If <code>pred?</code> returns <code>true</code> for every item in the sequence <code>all?</code> returns true. If <code>pred?</code> returns <code>false</code> for any item, then <code>all?</code> immediately returns <code>false</code>. <code>all?</code> returns <code>true</code> when the collection is empty.</p><pre><code>defn all?<?T> (pred?: T -> True|False, xs:Seqable<?T>) -> True|False</code></pre><p>These functions iterate through the given sequences in parallel and calls <code>pred?</code> on each pair (or triplet) of items from each sequence. Iteration stops as soon as any sequence is empty. <code>all?</code> returns <code>true</code> if all calls to <code>pred?</code> returns <code>true</code>. <code>all?</code> returns <code>false</code> immediately after a call to <code>pred?</code> returns <code>false</code>.</p><pre><code>defn all?<?T,?S> (pred?: (T,S) -> True|False,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>) -> True|False<br> <br>defn all?<?T,?S,?U> (pred?: (T,S,U) -> True|False,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>,<br> zs:Seqable<?U>) -> True|False</code></pre><h3 id="anchor496">none?</h3><p>This function iterates through the items in the sequence <code>xs</code> and calls <code>pred?</code> on each one. If <code>pred?</code> returns <code>true</code> for no item in the sequence then <code>none?</code> returns <code>true</code>. If <code>pred?</code> returns <code>true</code> for any item, then <code>none?</code> immediately returns <code>false</code>. <code>none?</code> returns <code>true</code> when the collection is empty.</p><pre><code>defn none?<?T> (pred?: T -> True|False, xs:Seqable<?T>) -> True|False</code></pre><p>These functions iterate through the given sequences in parallel and calls <code>pred?</code> on each pair (or triplet) of items from each sequence. Iteration stops as soon as any sequence is empty. <code>none?</code> returns <code>true</code> if no calls to <code>pred?</code> returns <code>true</code>. <code>none?</code> returns <code>false</code> immediately after a call to <code>pred?</code> returns <code>true</code>.</p><pre><code>defn none?<?T,?S> (pred?: (T,S) -> True|False,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>) -> True|False<br> <br>defn none?<?T,?S,?U> (pred?: (T,S,U) -> True|False,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>,<br> zs:Seqable<?U>) -> True|False</code></pre><h3 id="anchor497">any?</h3><p>This function iterates through the items in the sequence <code>xs</code> and calls <code>pred?</code> on each one. If <code>pred?</code> returns <code>true</code> for no item in the sequence then <code>any?</code> returns <code>false</code>. If <code>pred?</code> returns <code>true</code> for any item, then <code>any?</code> immediately returns <code>true</code>. <code>any?</code> returns <code>false</code> when the collection is empty.</p><pre><code>defn any?<?T> (pred?: T -> True|False, xs:Seqable<?T>) -> True|False</code></pre><p>These functions iterate through the given sequences in parallel and calls <code>pred?</code> on each pair (or triplet) of items from each sequence. Iteration stops as soon as any sequence is empty. <code>any?</code> returns <code>false</code> if no calls to <code>pred?</code> returns <code>true</code>. <code>any?</code> returns <code>true</code> immediately after a call to <code>pred?</code> returns <code>true</code>.</p><pre><code>defn any?<?T,?S> (pred?: (T,S) -> True|False,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>) -> True|False<br> <br>defn any?<?T,?S,?U> (pred?: (T,S,U) -> True|False,<br> xs:Seqable<?T>,<br> ys:Seqable<?S>,<br> zs:Seqable<?U>) -> True|False</code></pre><h3 id="anchor498">count</h3><p>This function iterates through the items in the sequence <code>xs</code> and calls <code>pred?</code> on each one. <code>count</code> returns the number of times that <code>pred?</code> returned <code>true</code>.</p><pre><code>defn count<?T> (pred?: T -> True|False, xs:Seqable<?T>) -> Int</code></pre><h3 id="anchor499">Sequence Constructors</h3><p>Sequence constructors are functions that take non-<code>Seq</code> objects and construct and return <code>Seq</code> objects from them.</p><h3 id="anchor500">repeat</h3><p>This function creates an infinite sequence resulting from repeating <code>x</code> indefinitely.</p><pre><code>defn repeat<?T> (x:?T) -> Seq<T></code></pre><p>This function creates a sequence resulting from repeating <code>x</code> for <code>n</code> number of times.</p><pre><code>defn repeat<?T> (x:?T, n:Int) -> Seq<T> & Lengthable</code></pre><h3 id="anchor501">repeatedly</h3><p>This function creates an infinite sequence from the results of calling <code>f</code> repeatedly.</p><pre><code>defn repeatedly<?T> (f:() -> ?T) -> Seq<T></code></pre><p>This function creates a sequence resulting from the results of calling <code>f</code> for <code>n</code> number of times.</p><pre><code>defn repeatedly<?T> (f:() -> ?T, n:Int) -> Seq<T> & Lengthable</code></pre><h3 id="anchor502">repeat-while</h3><p>This function creates a sequence resulting from calling <code>f</code> repeatedly and including, in the result sequence, the unwrapped values of every <code>One</code> object returned by <code>f</code>. The sequence ends as soon as <code>f</code> returns a <code>None</code> object.</p><pre><code>defn repeat-while<?T> (f: () -> Maybe<?T>) -> Seq<T></code></pre><h3 id="anchor503">Sequence Operators</h3><p>Sequence operators are functions that take <code>Seq</code> objects as arguments and return a new <code>Seq</code> object.</p><h3 id="anchor504">filter</h3><p>This function constructs a sequence by iterating through the <code>xs</code> and <code>sel</code> sequences in parallel and including items from the <code>xs</code> sequence in the result sequence only if the corresponding item from the <code>sel</code> sequence is <code>true</code>.</p><pre><code>defn filter<?T> (xs:Seqable<?T>, sel:Seqable<True|False>) -> Seq<T></code></pre><h3 id="anchor505">take-n</h3><p>This function constructs a sequence by taking the first <code>n</code> items from the <code>xs</code> sequence. The <code>xs</code> sequence must contain at least <code>n</code> items.</p><pre><code>defn take-n<?T> (n:Int, xs:Seqable<?T>) -> Seq<T></code></pre><h3 id="anchor506">take-up-to-n</h3><p>This function constructs a sequence by taking up to the first <code>n</code> items from the <code>xs</code> sequence.</p><pre><code>defn take-up-to-n<?T> (n:Int, xs:Seqable<?T>) -> Seq<T></code></pre><h3 id="anchor507">cat</h3><p>This function constructs a new sequence by concatenating the <code>a</code> sequence with the <code>b</code> sequence.</p><pre><code>defn cat<?T> (a:Seqable<?T>, b:Seqable<?T>) -> Seq<T></code></pre><h3 id="anchor508">cat-all</h3><p>This function constructs a new sequence by concatenating together all sequences in the <code>xss</code> sequence.</p><pre><code>defn cat-all<?T> (xss: Seqable<Seqable<?T>>) -> Seq<T></code></pre><h3 id="anchor509">join</h3><p>This function constructs a new sequence by including the item <code>y</code> in between each item in <code>xs</code>.</p><pre><code>defn join<?T,?S> (xs:Seqable<?T>, y:?S) -> Seq<T|S></code></pre><h3 id="anchor510">zip</h3> <p>This function constructs a new sequence by iterating through the sequences <code>xs</code> and <code>ys</code> in parallel and including the 2 element tuples formed from the items of each sequence. Iteration stops as soon as either sequence is empty.</p><pre><code>defn zip<?T,?S> (xs:Seqable<?T>, ys:Seqable<?S>) -> Seq<[T,S]></code></pre><p>This function constructs a new sequence by iterating through the sequences <code>xs</code>, <code>ys</code>, and <code>zs</code>, in parallel and including the 3 element tuples formed from the items of each sequence. Iteration stops as soon as any sequence is empty.</p><pre><code>defn zip<?T,?S,?U> (xs:Seqable<?T>,<br> ys:Seqable<?S>,<br> zs:Seqable<?U>) -> Seq<[T,S,U]></code></pre><h3 id="anchor511">zip-all</h3><p>This function constructs a new sequence by iterating through all sequences in <code>xss</code> in parallel, and including the tuples formed from the items of each sequence. Iteration stops as soon as any sequence is empty.</p><pre><code>defn zip-all<?T> (xss:Seqable<Seqable<?T>>) -> Seq<Tuple<T>></code></pre><h3 id="anchor512">Sequence Reducers</h3><p>Sequence reducers are functions that take <code>Seq</code> objects as arguments and compute and return a non-<code>Seq</code> object.</p><h3 id="anchor513">contains?</h3><p>This function returns <code>true</code> if the <code>xs</code> sequence contains the item <code>y</code>. Otherwise it returns <code>false</code>.</p><pre><code>defn contains? (xs:Seqable<Equalable>, y:Equalable) -> True|False</code></pre><h3 id="anchor514">index-of</h3><p>This function returns the first index at which the item in the <code>xs</code> sequence is equal to the item <code>y</code>. If no item in <code>xs</code> is equal to <code>y</code> then <code>index-of</code> returns <code>false</code>.</p><pre><code>defn index-of (xs:Seqable<Equalable>, y:Equalable) -> Int|False</code></pre><h3 id="anchor515">index-of!</h3><p>This function behaves identically to <code>index-of</code> except that it assumes there exists an item in <code>xs</code> that is equal to <code>y</code>.</p><pre><code>defn index-of! (xs:Seqable<Equalable>, y:Equalable) -> Int</code></pre><h3 id="anchor516">split</h3><p>This function iterates through the items in the <code>xs</code> and <code>ss</code> sequence in parallel, and separates the items from <code>xs</code> into two collections depending on whether the corresponding item from <code>ss</code> is <code>true</code> or <code>false</code>. The function returns a tuple of two collections, the first of which contains all items in <code>xs</code> for which the corresponding item in <code>ss</code> is <code>true</code>, and the second of which contains the other items in <code>xs</code>.</p><pre><code>defn split<?T> (xs:Seqable<?T>, ss:Seqable<True|False>) -><br> [Collection<T>&Lengthable, Collection<T>&Lengthable]</code></pre><h3 id="anchor517">count</h3><p>This function returns the number of items in the given sequence. If the sequence is a subtype of <code>Lengthable</code>, then the length is returned directly. Otherwise, the length is calculated by iterating through the entire sequence.</p><pre><code>defn count (xs:Seqable) -> Int</code></pre><h3 id="anchor518">reduce</h3><p>This function computes the left oriented reduction using function <code>f</code> on the sequence <code>xs</code> starting with initial value <code>x0</code>. If <code>xs</code> is empty then <code>x0</code> is returned. Otherwise, the function <code>f</code> is applied on <code>x0</code> and the first element in <code>xs</code>, then <code>f</code> is applied again on that result and the second element in <code>xs</code>, then <code>f</code> is applied on that result and the third element in <code>xs</code>, and so forth until <code>xs</code> is empty. <code>reduce</code> returns the final result returned by <code>f</code>.</p><pre><code>defn reduce<?T,?S> (f: (T, S) -> ?T, x0: ?T, xs:Seqable<?S>) -> T</code></pre><p>If no initial value is provided, then the first element in <code>xs</code> is used as the initial value of the reduction. <code>xs</code> must not be empty.</p><pre><code>defn reduce<?T,?S> (f: (T|S, T) -> ?S, xs:Seqable<?T>) -> T|S</code></pre><h3 id="anchor519">reduce-right</h3><p>This function computes the right oriented reduction using function <code>f</code> on the sequence <code>xs</code> with final value <code>xn</code>. If <code>xs</code> is empty then <code>xn</code> is returned. If <code>xs</code> has a single element, then <code>f</code> is applied on that element and <code>xn</code>. If <code>xs</code> has two elements, then f is applied on the first element and the result of applying <code>f</code> on the second element and <code>xn</code>. If <code>xs</code> has three elements, then <code>f</code> is applied on the first element and the result of applying <code>f</code> on the second element and the result of applying <code>f</code> on the third element and <code>xn</code>. Et cetera. </p><pre><code>defn reduce-right<?T,?S> (f: (S, T) -> ?T, xs:Seqable<?S>, xn:?T) -> T</code></pre><p>If no final value is provided, then the last element in <code>xs</code> is used as the final value of the reduction. <code>xs</code> must not be empty.</p><pre><code>defn reduce-right<?T,?S> (f: (T, T|S) -> ?S, xs:Seqable<?T>) -> T|S</code></pre><h3 id="anchor520">unique</h3><p>This function returns a list containing all unique items in the sequence <code>xs</code>.</p><pre><code>defn unique<?T> (xs:Seqable<?T&Equalable>) -> List<T></code></pre><h3 id="anchor521">lookup?</h3><p>This function iterates through the <code>xs</code> sequence, and looks for the first <code>KeyValue</code> pair whose key is equal to <code>k</code>. If such a pair is found, then its value is returned. If not then <code>default</code> is returned.</p><pre><code>defn lookup?<?K,?V,?D> (xs:Seqable<KeyValue<?K&Equalable,?V>>,<br> k:K&Equalable,<br> default:?D) -> D|V</code></pre><p>If no default value is provided, then <code>false</code> is returned if no appropriate <code>KeyValue</code> pair is found.</p><pre><code>defn lookup?<?K,?V> (xs:Seqable<KeyValue<?K&Equalable,?V>>,<br> k:K&Equalable) -> False|V</code></pre><h3 id="anchor522">lookup</h3><p>This function behaves identically to <code>lookup?</code> except that it assumes that an appropriate <code>KeyValue</code> pair exists and returns its value.</p><pre><code>defn lookup<?K,?V> (xs: Seqable<KeyValue<?K&Equalable,?V>>, k:K&Equalable) -> V</code></pre><h3 id="anchor523">fork-on-seq</h3><p>This function takes a sequence <code>xs</code>, and returns a tuple containing the results of calling the functions <code>f</code> and <code>g</code> with <code>xs</code>. The functions <code>f</code> and <code>g</code> are computed concurrently such that <code>xs</code> is iterated through only once. This function allows multiple values to be computed from a sequence that can only be iterated through once.</p><pre><code>defn fork-on-seq<?T,?X,?Y> (xs:Seqable<?T>,<br> f:Seq<T> -> ?X,<br> g:Seq<T> -> ?Y) -> [X,Y]</code></pre><p>This function takes a sequence <code>xs</code>, and returns a tuple containing the results of calling the functions <code>f</code>, <code>g</code>, and <code>h</code> with <code>xs</code>. The functions are computed concurrently such that <code>xs</code> is iterated through only once.</p><pre><code>defn fork-on-seq<?T,?X,?Y,?Z> (xs:Seqable<?T>,<br> f:Seq<T> -> ?X,<br> g:Seq<T> -> ?Y,<br> h:Seq<T> -> ?Z) -> [X,Y,Z]</code></pre><p>This function takes a sequence <code>xs</code>, and returns a tuple containing the results of calling every function in <code>fs</code> with <code>xs</code>. The functions are computed concurrently such that <code>xs</code> is iterated through only once.</p><pre><code>defn fork-on-seq<?T,?S> (xs:Seqable<?T>,<br> fs:Seqable<(Seq<T> -> ?S)>) -> Tuple<S></code></pre><h2 id="anchor524">Sorting</h2><p>Stanza's core library provides convenience functions for sorting collections.</p><h3 id="anchor525">qsort!</h3><p>This function sorts the collection using the given comparison function and the quick sort algorithm.</p><pre><code>defn qsort!<?T> (xs:IndexedCollection<?T>, is-less?:(T,T) -> True|False) -> False</code></pre><p>This function sorts the collection using the <code>less?</code> multi and using the quick sort algorithm.</p><pre><code>defn qsort!<?T> (xs:IndexedCollection<?T&Comparable>) -> False</code></pre><p>This function sorts the collection by comparing the keys extracted using the <code>key</code> function and using the quick sort algorithm.</p><pre><code>defn qsort!<?T> (key:T -> Comparable, xs:IndexedCollection<?T>) -> False</code></pre><h3 id="anchor526">lazy-qsort</h3><p>This function returns a lazily sorted sequence of the given sequence <code>xs</code> using the given comparison function and the quick sort algorithm.</p><pre><code>defn lazy-qsort<?T> (xs:Seqable<?T>,<br> is-less?:(T,T) -> True|False) -> Collection<T> & Lengthable</code></pre><p>This function returns a lazily sorted collection of the given sequence <code>xs</code> using the <code>less?</code> multi and the quick sort algorithm.</p><pre><code>defn lazy-qsort<?T> (xs:Seqable<?T&Comparable>) -> Collection<T> & Lengthable</code></pre><p>This function returns a lazily sorted collection of the given sequence <code>xs</code> by comparing keys extracted using the <code>key</code> function and using the quick sort algorithm.</p><pre><code>defn lazy-qsort<?T> (key:T -> Comparable,<br> xs:Seqable<?T>) -> Collection<T> & Lengthable</code></pre><h2 id="anchor527">LivenessTracker</h2><p>Stanza's support for automatic garbage collection means that users do not need to manually delete objects after their use. However, it is often useful to know when an object has been reclaimed to perform additional cleanup operations. <code>LivenessTracker</code> and <code>LivenessMarker</code> objects are used to track whether an object is still live. </p><pre><code>deftype LivenessTracker<T><br>deftype LivenessMarker</code></pre><h3 id="anchor528">LivenessTracker</h3><p>This function creates a <code>LivenessTracker</code> with an associated value to indicate the identity of the tracker.</p><pre><code>defn LivenessTracker<?T> (value:?T) -> LivenessTracker<T></code></pre><h3 id="anchor529">value</h3><p>This function can be used to retrieve the value associated with a tracker.</p><pre><code>defn value<?T> (tracker:LivenessTracker<?T>) -> T</code></pre><h3 id="anchor530">marker</h3><p>This function is used to create or check upon a <code>LivenessMarker</code>.</p><pre><code>defn marker (tracker:LivenessTracker) -> False|LivenessMarker</code></pre><p>The first time this function is called on a <code>LivenessTracker</code> it is guaranteed to return its associated <code>LivenessMarker</code>. This marker may then be stored with an object whose liveness the user wishes to track. On subsequent calls to <code>marker</code>, the function will either return the created marker, which indicates that the marker is still live. Or it will return <code>false</code>, which indicates that the marker is now longer live, and hence neither is the object in which it is stored.</p><p>For example, consider tracking the liveness of values of type <code>Car</code>. Intuitively, it is helpful to imagine a <code>LivenessTracker</code> as a futuristic pistol capable of shooting a tracking beacon (its <code>LivenessMarker</code>) that sticks to the <code>Car</code>. Periodically, you may ask the tracker whether it is still receiving signal from the beacon, in which case the marker and hence the <code>Car</code> is still live. If the beacon is no longer sending a signal (<code>marker</code> returns <code>false</code>), then the marker and hence the <code>Car</code> is no longer live.</p><h3 id="anchor531">marker!</h3><p>This function assumes that <code>marker</code> will return a <code>LivenessMarker</code> and returns it.</p><pre><code>defn marker! (tracker:LivenessTracker) -> LivenessMarker</code></pre><h3 id="anchor532">add-gc-notifier</h3><p>This function registers a new garbage collection notifier with Stanza. Garbage collection notifiers are run after every garbage collection phase.</p><pre><code>defn add-gc-notifier (f: () -> ?) -> False</code></pre><h2 id="anchor533">Files & Directories</h2><p></p><h3 id="anchor534">file-exists?</h3><p>This function checks whether the given file exists given its name.</p><pre><code>defn file-exists? (filename:String) -> True|False</code></pre><h3 id="anchor535">file-type</h3><p>These functions return the type of file in the passed <code>filename</code>. If <code>follow-symlinks?</code> is true, then the symlink is followed to its target and the type of the target filepath is returned. This function throws <code>FileTypeException</code> on error. By default, this function will follow symlinks. </p><pre><code>defn file-type (filename:String, follow-symlinks?:True|False) -> FileType<br>defn file-type (filename:String) -> FileType</code></pre><p>The <code>FileType</code> has several subtypes:</p><ul>
<li><code>RegularFileType</code></li>
<li><code>DirectoryType</code></li>
<li><code>SymbolicLinkType</code></li>
<li><code>OtherType</code></li>
</ul><h3 id="anchor536">rename-file</h3><p>This function renames a file from <code>path</code> to <code>new-path</code>. This function will throw <code>FileRenameError</code> on failure. See <a href=https://man7.org/linux/man-pages/man2/rename.2.html>rename</a> for more information.</p><pre><code>defn rename-file (path:String, new-path:String) -> False</code></pre><h3 id="anchor537">copy-file</h3><p>This function copies the contents of <code>old-path</code> to <code>new-path</code>, creating the <code>new-path</code> file if it doesn't exist. See <code>RandomAccessFile</code> for more info.</p><pre><code>defn copy-file (old-path:String, new-path:String) -> False</code></pre><h3 id="anchor538">symlink</h3><p>This function creates a symlink at <code>linkpath</code> that points to <code>target</code> path. This function will throw <code>SymLinkError</code> on failure.</p><pre><code>defn symlink (target:String, linkpath:String) -> False</code></pre><h3 id="anchor539">delete-file</h3><p>This function deletes the given file.</p><pre><code>defn delete-file (path:String) -> False</code></pre><h3 id="anchor540">delete-recursive</h3><p>This function deletes the given path and if it is a directory, recursively deletes all files and directories inside that directory. If the <code>follow-symlinks?</code> argument is <code>true</code>, then any symlinks encountered during the descent will be followed and if the symlink points to a directory, the source of the symlink will also be deleted. Symlinks that point to other files will only delete the symlink and not the source file.</p><pre><code>defn delete-recursive (path:String, follow-symlinks?:True|False) -> False</code></pre><h3 id="anchor541">resolve-path</h3><p>This function expands all symbolic links in the given path and returns an absolute path that points to the same file. If such a file does not exist then <code>false</code> is returned. The <code>resolve-path!</code> variant will thows a <code>PathResolutionError</code> exception on error.</p><pre><code>defn resolve-path (path:String) -> String|False<br>defn resolve-path! (path:String) -> String</code></pre><h3 id="anchor542">split-filepath</h3><p>This function splits the passed <code>path</code> into two parts by looking for the last '/' character in <code>path</code>. If <code>path</code> is empty, then this function throws a <code>EmptyPath</code> exception. If <code>path</code> ends with a '/', then this function throws a <code>PathEndsWithSlash</code> exception. Both of these exceptions are subtypes of <code>PathException</code>.</p><p>NOTE: This function will not work with window's drive paths like <code>C:\Users\foo</code> that use the '\' character as path separator.</p><pre><code>defn split-filepath (path:String) -> [String, String]</code></pre><h3 id="anchor543">dir-files</h3><p>These functions return a tuple of strings containing the names of the files in the given directory <code>dirname</code>. The <code>include-parents?</code> flag is used to filter out the "." and ".." directories if present. These functions may throw <code>DirException</code> on error. For more information see <a href=https://man7.org/linux/man-pages/man3/readdir.3p.html>readdir</a>.</p><pre><code>defn dir-files (dirname:String, include-parents?:True|False) -> [String]<br>defn dir-files (dirname:String) -> [String]</code></pre><h3 id="anchor544">create-dir</h3><p>This function will create the passed <code>dirname</code> directory. If the <code>permissions</code> parameter is not provided, the default permissions will be <code>0o777</code>. This function will throw a <code>CreateDirException</code> on error. See <a href=https://man7.org/linux/man-pages/man2/mkdir.2.html>mkdir</a> for more info.</p><pre><code>defn create-dir (dirname:String, permissions:Int) -> False<br>defn create-dir (dirname:String) -> False</code></pre><h3 id="anchor545">create-dir-recursive</h3><p>This function will create directories needed for the steps in the passed <code>filepath</code>. This function behaves like <code>mkdir -p</code>. If <code>permissions</code> is not passed, then the default permissions of <code>0o777</code> will be used. On error, this function will throw <code>CreateDirException</code> or <code>CreateRecursiveDirException</code>.</p><pre><code>defn create-dir-recursive (filepath:String, permissions:Int) -> False<br>defn create-dir-recursive (filepath:String) -> False</code></pre><h2 id="anchor546">System Utilities</h2><p>Stanza's core library provides convenience functions for manipulating the system environment.</p><h3 id="anchor547">command-line-arguments</h3><p>The command line arguments used to invoke the program can be retrieved as an array of strings using the following function.</p><pre><code>defn command-line-arguments () -> Array<String></code></pre><h3 id="anchor548">current-time-ms</h3><p>This function returns the number of milliseconds elapsed since January 1, 1970.</p><pre><code>defn current-time-ms () -> Long</code></pre><h3 id="anchor549">current-time-us</h3><p>This function returns the number of microseconds elapsed since January 1, 1970.</p><pre><code>defn current-time-us () -> Long</code></pre><h3 id="anchor550">get-env</h3><p>This function returns the value associated with the environment variable with the given name. <code>false</code> is returned if there is no such variable.</p><pre><code>defn get-env (name:String) -> String|False</code></pre><h3 id="anchor551">set-env</h3><p>These functions associate the environment variable of the given name with the given value. If the environment variable already exists then its value is overwritten if the <code>overwrite</code> flag is <code>true</code>, otherwise its old value is kept. If no <code>overwrite</code> flag is given then its default value is <code>true</code>.</p><pre><code>defn set-env (name:String, value:String, overwrite:True|False) -> False<br>defn set-env (name:String, value:String) -> False</code></pre><h3 id="anchor552">unset-env</h3><p>This function deletes a variable <code>name</code> from the environment. If <code>name</code> does not exist, this function leaves the environment unchanged and returns successfully. This function will throw a <code>UnsetEnvException</code> on error. See <a href=https://man7.org/linux/man-pages/man3/setenv.3.html>unsetenv</a> from the standard C library.</p><pre><code>defn unset-env (name:String) -> False</code></pre><h3 id="anchor553">call-system</h3><p>This function executes the given program with the given arguments. The sequence of strings for <code>args</code> is passed to the traditional <code>char** argvs</code> argument for the C <code>main</code> function. Note that because of this, the first item in <code>args</code> is expected to be the name of the program itself. </p><p>If the call fails with an error then the function throws a <code>SystemCallException</code>, otherwise it returns the integer status code of the call.</p><pre><code>defn call-system (file:String, args:Seqable<String>) -> Int</code></pre><h3 id="anchor554">call-system-and-get-output</h3><p>This function executes the given program with the given arguments. The sequence of strings for <code>args</code> is passed to the traditional <code>char** argvs</code> argument for the C <code>main</code> function. Note that because of this, the first item in <code>args</code> is expected to be the name of the program itself.</p><p>If the call fails with an error then the function throws a <code>SystemCallException</code>, otherwise it returns the printed output from the program output and error streams. </p><pre><code>defn call-system-and-get-output (file:String, args:Seqable<String>) -> String</code></pre><h3 id="anchor555">replace-current-process</h3><p>This function replaces the current process with the execution of the given program with the given arguments. The sequence of strings for <code>args</code> is passed to the traditional <code>char** argvs</code> argument for the C <code>main</code> function. Note that because of this, the first item in <code>args</code> is expected to be the name of the program itself.</p><p>If the call fails with an error then the function throws a <code>SystemCallException</code>, otherwise the current process is replaced.</p><p>If the <code>resolve-path?</code> argument is set to <code>true</code>, then the <code>path</code> argument is looked up using standard system shell conventions: e.g. it first looks in the directories listed on the <code>PATH</code>, etc. Otherwise, the <code>path</code> should point to a concrete file. The <code>resolve-path?</code> argument is <code>true</code> by default.</p><pre><code>defn replace-current-process (path:String,<br> args:Tuple<String>,<br> resolve-path?:True|False) -> Void<br>defn replace-current-process (path:String,<br> args:Tuple<String>) -> Void</code></pre><h3 id="anchor556">exit</h3><p>This function will call the underlying libc <a href=https://man7.org/linux/man-pages/man3/exit.3.html>exit</a> function.</p><pre><code>defn exit (code:Int) -> Void</code></pre><h2 id="anchor557">Timer</h2><p><code>Timers</code> are used for measuring elapsed time at various granularities.</p><pre><code>deftype Timer</code></pre><h3 id="anchor558">MillisecondTimer</h3><p>This function creates a timer with millisecond granularity and an associated name.</p><pre><code>defn MillisecondTimer (name:String) -> Timer</code></pre><h3 id="anchor559">MicrosecondTimer</h3><p>This function creates a timer with microsecond granularity and an associated name.</p><pre><code>defn MicrosecondTimer (name:String) -> Timer</code></pre><h3 id="anchor560">PiggybackTimer</h3><p>This function creates a timer that piggybacks off of the time measured by another timer. Time only elapses for a piggyback timer if the timer it is piggybacking is running. A <code>PiggybackTimer</code> returns time in the same granularity as the timer it is piggybacking.</p><pre><code>defn PiggybackTimer (name:String, t:Timer) -> Timer</code></pre><h3 id="anchor561">start</h3><p>This function starts the timer. It is an error to start a <code>Timer</code> that is already running.</p><pre><code>defn start (t:Timer) -> False</code></pre><h3 id="anchor562">stop</h3><p>This function stops the timer. It is an error to stop a <code>Timer</code> that is not running.</p><pre><code>defn stop (t:Timer) -> False</code></pre><h3 id="anchor563">time</h3><p>This function retrieves the current time elapsed by the timer. The unit of the number returned is dependent upon how the timer is created.</p><pre><code>defn time (t:Timer) -> Long</code></pre><h1 id="anchor564">Math Package</h1><p>The <code>math</code> package contains basic mathematical quantities and operations.</p><h2 id="anchor565">Quantities</h2><p></p><h3 id="anchor566">PI</h3><p>This value contains a double-precision definition of the mathematical quantity pi.</p><pre><code>val PI : Double</code></pre><h3 id="anchor567">PI-F</h3><p>This value contains a single-precision definition of the mathematical quantity pi.</p><pre><code>val PI-F : Float</code></pre><h2 id="anchor568">Basic Operations</h2><p></p><h3 id="anchor569">exp</h3><p>This function computes e to the power of <code>x</code>.</p><pre><code>defn exp (x:Double) -> Double<br>defn exp (x:Float) -> Float</code></pre><h3 id="anchor570">log</h3><p>This function computes the natural logarithm of <code>x</code>.</p><pre><code>defn log (x:Double) -> Double<br>defn log (x:Float) -> Float</code></pre><h3 id="anchor571">log10</h3><p>This function computes the base 10 logarithm of <code>x</code>.</p><pre><code>defn log10 (x:Double) -> Double<br>defn log10 (x:Float) -> Float</code></pre><h3 id="anchor572">pow</h3><p>This function computes <code>x</code> to the power of <code>y</code>.</p><pre><code>defn pow (x:Double, y:Double) -> Double<br>defn pow (x:Float, y:Float) -> Float</code></pre><h3 id="anchor573">sin</h3><p>This function computes the sine of <code>x</code>.</p><pre><code>defn sin (x:Double) -> Double<br>defn sin (x:Float) -> Float</code></pre><h3 id="anchor574">cos</h3><p>This function computes the cosine of <code>x</code>.</p><pre><code>defn cos (x:Double) -> Double<br>defn cos (x:Float) -> Float</code></pre><h3 id="anchor575">tan</h3><p>This function computes the tangent of <code>x</code>.</p><pre><code>defn tan (x:Double) -> Double<br>defn tan (x:Float) -> Float</code></pre><h3 id="anchor576">asin</h3><p>This function computes the inverse sine of <code>x</code>.</p><pre><code>defn asin (x:Double) -> Double<br>defn asin (x:Float) -> Float</code></pre><h3 id="anchor577">acos</h3><p>This function computes the inverse cosine of <code>x</code>.</p><pre><code>defn acos (x:Double) -> Double<br>defn acos (x:Float) -> Float</code></pre><h3 id="anchor578">atan</h3><p>This function computes the inverse tangent of <code>x</code>.</p><pre><code>defn atan (x:Double) -> Double<br>defn atan (x:Float) -> Float</code></pre><h3 id="anchor579">atan2</h3><p>This function computes the inverse tangent of <code>y</code> divided by <code>x</code>. The signs of both arguments are used to determine the quadrant of the result.</p><pre><code>defn atan2 (y:Double, x:Double) -> Double<br>defn atan2 (y:Float, x:Float) -> Float</code></pre><h3 id="anchor580">sinh</h3><p>This function computes the hyperbolic sine of <code>x</code>.</p><pre><code>defn sinh (x:Double) -> Double<br>defn sinh (x:Float) -> Float</code></pre><h3 id="anchor581">cosh</h3><p>This function computes the hyperbolic cosine of <code>x</code>.</p><pre><code>defn cosh (x:Double) -> Double<br>defn cosh (x:Float) -> Float</code></pre><h3 id="anchor582">tanh</h3><p>This function computes the hyperbolic tangent of <code>x</code>.</p><pre><code>defn tanh (x:Double) -> Double<br>defn tanh (x:Float) -> Float</code></pre><h3 id="anchor583">ceil</h3><p>This function computes the ceiling of <code>x</code>.</p><pre><code>defn ceil (x:Double) -> Double<br>defn ceil (x:Float) -> Float</code></pre><h3 id="anchor584">floor</h3><p>This function computes the floor of <code>x</code>.</p><pre><code>defn floor (x:Double) -> Double<br>defn floor (x:Float) -> Float</code></pre><h3 id="anchor585">round</h3><p>This function rounds <code>x</code> to the nearest integer.</p><pre><code>defn round (x:Double) -> Double<br>defn round (x:Float) -> Float</code></pre><h3 id="anchor586">to-radians</h3><p>This function converts an angle expressed in degrees to radians.</p><pre><code>defn to-radians (x:Double) -> Double<br>defn to-radians (x:Float) -> Float</code></pre><h3 id="anchor587">to-degrees</h3><p>This function converts an angle expressed in radians to degrees.</p><pre><code>defn to-degrees (x:Double) -> Double<br>defn to-degrees (x:Float) -> Float</code></pre><h1 id="anchor588">Collections Package</h1><p>The <code>collections</code> package consists of functions and types useful for managing collection datastructures. </p><h2 id="anchor589">Vector</h2><p>A <code>Vector</code> object represents a dynamically growing array of items. Like arrays, each item can be accessed using an integer index. However, a <code>Vector</code> object can be resized after creation.</p><pre><code>deftype Vector<T> <: IndexedCollection<T></code></pre><p><code>Vector</code> is a subtype of <code>IndexedCollection</code> and thus implements the appropriate methods for retrieving elements, assigning elements, and retrieving its length. When assigning an item, <code>v</code>, to an index <code>i</code>, if <code>i</code> is less than the length of the vector then the item at that location is overwritten by <code>v</code>. If <code>i</code> is equal to the length of the vector, then <code>v</code> is added to the end of the vector.</p><h3 id="anchor590">Vector</h3><p>This function creates a <code>Vector</code> for holding objects of type <code>T</code> initialized with a capacity of <code>cap</code>.</p><pre><code>defn Vector<T> (cap:Int) -> Vector<T></code></pre><p>If no capacity is given, then the default capacity is <code>8</code>.</p><pre><code>defn Vector<T> () -> Vector<T></code></pre><h3 id="anchor591">to-vector</h3><p>This function creates a new <code>Vector</code> from the elements in the sequence <code>xs</code>.</p><pre><code>defn to-vector<T> (xs:Seqable<T>) -> Vector<T></code></pre><h3 id="anchor592">add</h3><p>This function adds the given value to the end of the vector.</p><pre><code>defn add<?T> (v:Vector<?T>, value:T) -> False</code></pre><h3 id="anchor593">add-all</h3><p>This function adds all of the values in the sequence <code>vs</code> to the end of the vector.</p><pre><code>defn add-all<?T> (v:Vector<?T>, vs:Seqable<T>) -> False</code></pre><h3 id="anchor594">clear</h3><p>This function removes every item in the vector.</p><pre><code>defn clear (v:Vector) -> False</code></pre><h3 id="anchor595">pop</h3><p>This function removes the last item in the vector and returns it. The vector must not be empty.</p><pre><code>defn pop<?T> (v:Vector<?T>) -> T</code></pre><h3 id="anchor596">peek</h3><p>This function returns the last item in the vector. The vector must not be empty.</p><pre><code>defn peek<?T> (v:Vector<?T>) -> T</code></pre><h3 id="anchor597">remove</h3><p>This function removes the item at index <code>i</code> in the vector and returns the removed item. <code>i</code> must be less than the length of the vector. The operation takes time proportional to the difference between the length of the vector and <code>i</code>.</p><pre><code>defn remove<?T> (v:Vector<?T>, i:Int) -> T</code></pre><h3 id="anchor598">remove</h3><p>This function removes the items within the range <code>r</code> from the vector. The range must be a <span style="font-style:italic;">dense index range</span> with respect to the vector. The operation takes time proportional to the difference between the length of the vector and the end of the range.</p><pre><code>defn remove (v:Vector, r:Range) -> False</code></pre><h3 id="anchor599">update</h3><p>This function either overwrites or removes items from the vector by calling the function <code>f</code> on each item in the vector. For each item in the vector, if <code>f</code> returns a <code>One</code> object, then the item is overwritten with the wrapped value in the <code>One</code> object. If <code>f</code> returns a <code>None</code> object, then the item is removed from the vector. <code>update</code> is compatible with the <code>for</code> macro form.</p><pre><code>defn update<?T> (f: T -> Maybe<T>, v:Vector<?T>) -> False</code></pre><h3 id="anchor600">remove-item</h3><p>This function removes the first occurrence of the item <code>x</code> in the vector <code>v</code> if it exists. The function returns <code>true</code> if an item was removed, or <code>false</code> otherwise.</p><pre><code>defn remove-item<?T> (v:Vector<?T&Equalable>, x:T&Equalable) -> True|False</code></pre><h3 id="anchor601">remove-when</h3><p>This function calls the function <code>f</code> on every item in the vector <code>v</code>. Items for which <code>f</code> returned <code>true</code> are removed.</p><pre><code>defn remove-when<?T> (f: T -> True|False, v:Vector<?T>) -> False </code></pre><h3 id="anchor602">trim</h3><p>This function sets the capacity of the vector to be equal to the size of the vector, thus removing storage for additional elements.</p><pre><code>defn trim (v:Vector) -> False </code></pre><h3 id="anchor603">shorten</h3><p>This function truncates the given vector down to the specified size. The given size must be less than or equal to the length of the vector.</p><pre><code>defn shorten (v:Vector, size:Int) -> False</code></pre><h3 id="anchor604">lengthen</h3><p>This function pads the given vector up to the specified size by adding <code>x</code> repeatedly to the end of the vector. The given size must be greater than or equal to the length of the vector.</p><pre><code>defn lengthen<?T> (v:Vector<?T>, size:Int, x:T) -> False</code></pre><h3 id="anchor605">set-length</h3><p>This function sets the length of the vector to the new specified length. If the given length is shorter than the current length then the vector is truncated. Otherwise the vector is padded using the item <code>x</code>.</p><pre><code>defn set-length<?T> (v:Vector<?T>, length:Int, x:T) -> False </code></pre><h3 id="anchor606">map</h3><p>This function creates a new <code>Vector</code> from the results of applying the function <code>f</code> repeatedly to each item in the given vector <code>v</code>. Note that the element type, <code>R</code>, of the result vector must be given explicitly.</p><pre><code>defn map<R,?T> (f: T -> R, v:Vector<?T>) -> Vector<R></code></pre><h2 id="anchor607">Queue</h2><p>A <code>Queue</code> represents an indexed collection with support for acting as a first in last out (FIFO) datastructure.</p><pre><code>deftype Queue<T> <: IndexedCollection<T></code></pre><p><code>Queue</code> is a subtype of <code>IndexedCollection</code> and thus implements the appropriate methods for retrieving elements, assigning elements, and retrieving its length. When assigning an item, <code>v</code>, to an index <code>i</code>, if <code>i</code> is not negative and less than the length of the queue then the item at that location is overwritten by <code>v</code>. If i is equal to <code>-1</code>, then <code>v</code> is added to the front of the queue.</p><h3 id="anchor608">Queue</h3><p>This function creates a <code>Queue</code> for holding objects of type <code>T</code> initialized with a capacity of <code>cap</code>.</p><pre><code>defn Queue<T> (cap:Int) -> Queue<T></code></pre><p>If no capacity is given, then the default capacity is <code>8</code>.</p><pre><code>defn Queue<T> () -> Queue<T></code></pre><h3 id="anchor609">add</h3><p>This function adds the given item to the front of the queue. The corresponding indices of all existing entries in the queue increase by <code>1</code>.</p><pre><code>defn add<?T> (q:Queue<?T>, x:T) -> False</code></pre><h3 id="anchor610">pop</h3><p>This function removes and returns the item at the back of the queue. The queue must not be empty.</p><pre><code>defn pop<?T> (q:Queue<?T>) -> T</code></pre><h3 id="anchor611">peek</h3><p>This function returns the item at the back of the queue. The queue must not be empty.</p><pre><code>defn peek<?T> (q:Queue<?T>) -> T</code></pre><h3 id="anchor612">clear</h3><p>This function removes all items in the queue.</p><pre><code>defn clear (q:Queue) -> False</code></pre><h2 id="anchor613">Set</h2><p>A <code>Set</code> represents a collection unique items of type <code>K</code>.</p><pre><code>deftype Set<K> <: Collection<K> & Lengthable</code></pre><p><code>Set</code> is a subtype of <code>Collection</code> and must implement an appropriate method for the <code>to-seq</code> multi that allows for the set to be viewed as a sequence of <code>K</code> items.</p><p><code>Set</code> is a subtype of <code>Lengthable</code> and must implement an appropriate method for the <code>length</code> multi that returns the number of unique items in the set.</p><p>Mandatory minimal implementation: <code>to-seq</code>, <code>length</code>, <code>add</code>, <code>remove</code>, <code>get</code>, <code>clear</code>.</p><h3 id="anchor614">add</h3><pre><code>defmulti add<?K> (s:Set<?K>, k:K) -> True|False</code></pre><p>This multi adds the given item <code>k</code> to the set <code>s</code>. If the item was added succesfully, i.e. the item did not already exist in the set, then <code>add</code> returns <code>true</code>. Otherwise, the multi returns <code>false</code>.</p><h3 id="anchor615">remove</h3><pre><code>defmulti remove<?K> (s:Set<?K>, k:K) -> True|False</code></pre><p>This multi removes the given item <code>k</code> from the set <code>s</code>. If the item was removed succesfully, i.e. the item existed in the set, then <code>remove</code> returns <code>true</code>. Otherwise, the multi returns <code>false</code>.</p><h3 id="anchor616">get</h3><pre><code>defmulti get<?K> (s:Set<?K>, k:K) -> True|False</code></pre><p>This multi checks whether the given item <code>k</code> exists in the set <code>s</code>. </p><h3 id="anchor617">clear</h3><pre><code>defmulti clear (s:Set) -> False</code></pre><p>This multi removes all items from the given set.</p><h2 id="anchor618">Table</h2><p>A <code>Table</code> represents a mapping between key objects of type <code>K</code> and value objects of type <code>V</code>.</p><pre><code>deftype Table<K,V> <: Collection<KeyValue<K,V>> & Lengthable </code></pre><p><code>Table</code> is a subtype of <code>Collection</code> and must implement an appropriate method for the <code>to-seq</code> multi that allows for the table to be viewed as a sequence of <code>KeyValue</code> pairs.</p><p><code>Table</code> is a subtype of <code>Lengthable</code> and must implement an appropriate method for the <code>length</code> multi that returns the number of <code>KeyValue</code> pairs currently in the table.</p><p>Mandatory minimal implementation: <code>to-seq</code>, <code>length</code>, <code>set</code>, <code>get?</code>, <code>default?</code>, <code>remove</code>, <code>clear</code>.</p><h3 id="anchor619">set</h3><p>This multi associates the key object <code>k</code> with the value object <code>v</code> in the table.</p><pre><code>defmulti set<?K,?V> (t:Table<?K,?V>, k:K, v:V) -> False</code></pre><h3 id="anchor620">get?</h3><p>This multi retrieves the value object associated with the key object <code>k</code> in the table. If there is no such key in the table then the default value <code>d</code> is returned.</p><pre><code>defmulti get?<?K,?V,?D> (t:Table<?K,?V> k:K, d:?D) -> V|D</code></pre><h3 id="anchor621">default?</h3><p>This multi returns the optional default value associated with the table. If a default value is provided then it is returned when accessing keys that do not exist in the table.</p><pre><code>defmulti default?<?V> (t:Table<?,?V>) -> Maybe<V></code></pre><h3 id="anchor622">remove</h3><p>This multi removes the given key and its associated value from the table. If there is a key then the function returns <code>true</code>. Otherwise the function returns <code>false</code>.</p><pre><code>defmulti remove<?K> (t:Table<?K,?>, k:K) -> True|False</code></pre><h3 id="anchor623">clear</h3><p>This multi removes all keys and all values in the table.</p><pre><code>defmulti clear (t:Table) -> False</code></pre><h3 id="anchor624">get?</h3><p>This function returns the value associated with the given key if it exists, otherwise it returns <code>false</code>.</p><pre><code>defn get?<?K,?V> (t:Table<?K,?V>, k:K) -> V|False</code></pre><h3 id="anchor625">get</h3><p>This multi assumes that the given <code>k</code> exists in the table and returns its associated value, or that a default value is provided. A default method, defined in terms of <code>get?</code>, is provided but users may provide customized methods for subtypes of <code>Table</code> for efficiency purposes.</p><pre><code>defmulti get<?K,?V> (t:Table<?K,?V>, k:K) -> V</code></pre><h3 id="anchor626">key?</h3><p>This multi returns <code>true</code> if the given key <code>k</code> exists in the table. A default method, defined in terms of <code>get?</code>, is provided but users may provide customized methods for subtypes of <code>Table</code> for efficiency purposes.</p><pre><code>defmulti key?<?K> (t:Table<?K,?>, k:K) -> True|False </code></pre><h3 id="anchor627">keys</h3><p>This multi returns a sequence containing all keys in the table. A default method, defined in terms of <code>to-seq</code>, is provided but users may provide customized methods for subtypes of <code>Table</code> for efficiency purposes.</p><pre><code>defmulti keys<?K> (t:Table<?K,?>) -> Seqable<K> </code></pre><h3 id="anchor628">values</h3><p>This multi returns a sequence containing all values in the table. A default method, defined in terms of <code>to-seq</code>, is provided but users may provide customized methods for subtypes of <code>Table</code> for efficiency purposes.</p><pre><code>defmulti values<?V> (t:Table<?,?V>) -> Seqable<V></code></pre><h3 id="anchor629">empty?</h3><p>This function returns <code>true</code> if the table contains no keys or values.</p><pre><code>defn empty? (t:Table) -> True|False</code></pre><h2 id="anchor630">HashTable</h2><p>A <code>HashTable</code> provides an efficient implementation of tables for keys of type <code>Equalable</code>. Key type <code>K</code> must be a subtype of <code>Equalable</code>.</p><pre><code>deftype HashTable<K,V> <: Table<K,V></code></pre><p><code>HashTable</code> is a subtype of <code>Table</code> and support all necessary methods for correct table operations.</p><h3 id="anchor631">HashTable</h3><p>This function creates a <code>HashTable</code> with key objects of type <code>K</code> and value objects of type <code>V</code>. A <code>hash</code> function that maps key objects to integers, an optional default value, and an initial capacity must be provided. If provided, the default value is returned for retrieval operations when the key does not exist.</p><pre><code>defn HashTable<K,V> (hash: K -> Int,<br> default:Maybe<V>,<br> initial-capacity:Int) -> HashTable<K,V></code></pre><p>If unspecified, the default capacity is <code>32</code>.</p><pre><code>defn HashTable<K,V> (hash: K -> Int, default:V) -> HashTable<K,V></code></pre><p>If unspecified, then there is no default value.</p><pre><code>defn HashTable<K,V> (hash: K -> Int) -> HashTable<K,V></code></pre><p>This function creates a <code>HashTable</code> that uses the <code>hash</code> multi to compute hashes for its keys, and a default value of <code>V</code>. <code>K</code> must be a subtype of both <code>Hashable</code> and <code>Equalable</code>.</p><pre><code>defn HashTable<K,V> (default:V) -> HashTable<K,V></code></pre><p>If unspecified, then there is no default value.</p><pre><code>defn HashTable<K,V> () -> HashTable<K,V></code></pre><h1 id="anchor632">Reader Package</h1><p>The <code>reader</code> package contains the implementation of Stanza's s-expression reader.</p><h3 id="anchor633">read-file</h3><p>This function reads in the given file and returns its contents as a list of s-expressions.</p><pre><code>defn read-file (filename:String) -> List</code></pre><h3 id="anchor634">read-all</h3><p>This function converts the given string into a list of s-expressions.</p><pre><code>defn read-all (text:String) -> List</code></pre><h3 id="anchor635">read-all</h3><p>This function reads in all characters from the given string input stream and returns a list of s-expressions.</p><pre><code>defn read-all (stream:StringInputStream) -> List</code></pre><h3 id="anchor636">read</h3><p>This function reads a single s-expression from the string input stream.</p><pre><code>defn read (stream:StringInputStream) -> ?</code></pre> <h1 id="anchor637">Macro Utilities Package</h1><p>The <code>macro-utils</code> package contains functions for manipulating s-expressions useful for macro writers.</p><h2 id="anchor638">Utility Functions</h2><p></p><h3 id="anchor639">tagged-list?</h3><p>This function returns <code>true</code> if the given form is a list (or list wrapped in a <code>Token</code>) whose first element is equal to the given symbol, or is a token whose wrapped value is equal to the given symbol.</p><pre><code>defn tagged-list? (form, tag:Symbol) -> True|False</code></pre><h2 id="anchor640">S-Expression Template Engine</h2><p>The template engine can be thought of as an advanced search and replace utility that operates on s-expressions instead of on strings. </p><h3 id="anchor641">fill-template</h3><p>This function returns the result of performing search and replace operations on a template form given a collection of desired replacements.</p><pre><code>defn fill-template (template, replacements:Collection<KeyValue<Symbol,?>>) -> ?</code></pre><p>The replacements are expressed as <code>KeyValue</code> pairs where the key holds the symbol that should be replaced, and the value holds what the key should be replaced by. Values can be objects of any type, but there are a set of distinguished template forms with special replacement rules.</p><h3 id="anchor642">Simple Replacements</h3><p>Consider the following template :</p><pre><code>val form = `(<br> defn myfunction (arg : argtype) :<br> body)</code></pre><p>and the desired replacements :</p><pre><code>val replacements = [<br> `myfunction => `print-int<br> `arg => `x<br> `argtype => `Int<br> `body => `(println("Inside print-int"),<br> println(x))]</code></pre><p>Then the following call to <code>fill-template</code> :</p><pre><code>fill-template(form, replacements)</code></pre><p>will return the following replaced form :</p><pre><code>`(defn print-int (x : Int) :<br> (println("Inside print-int"),<br> println(x)))</code></pre><p>Observe that occurrences of the keys in <code>replacements</code> in the template form are systematically replaced with their associated values.</p><h3 id="anchor643">Splice Template</h3><p>The splice template allows for a symbol to be replaced by multiple values. The following function creates a splice template. Note that the given item must be either a <code>Collection</code> or a <code>Token</code> wrapping over a <code>Collection</code>.</p><pre><code>defn splice (item:Collection|Token) -> SpliceTemplate</code></pre><p>Consider again the previous example. Notice that, the key <code>`body</code> was associated with a 2 element list. And in the resulting form, the occurrence of <code>body</code> was replaced with the 2 element list.</p><p>By using the splice template we can replace occurrences of <code>`body</code> directly with the elements inside the list and avoid an extra pair of parenthesis.</p><p>Consider the following template :</p><pre><code>val form = `(<br> defn myfunction (arg : argtype) :<br> body)</code></pre><p>and the desired replacements :</p><pre><code>val replacements = [<br> `myfunction => `print-int<br> `arg => `x<br> `argtype => `Int<br> `body => splice(`(println("Inside print-int"),<br> println(x)))]</code></pre><p>Then the following call to <code>fill-template</code> :</p><pre><code>fill-template(form, replacements)</code></pre><p>will return the following replaced form :</p><pre><code>`(defn print-int (x : Int) :<br> println("Inside print-int")<br> println(x))</code></pre><h3 id="anchor644">Nested Template</h3><p>The nested template allows for a pattern to be repeatedly replaced using a different set of replacements each time. The following function creates a nested template.</p><pre><code>defn nested (items:Collection<Collection<KeyValue<Symbol,?>>>) -> NestedTemplate</code></pre><p>Consider the following template :</p><pre><code>val form = `(<br> defn myfunction (args{arg : argtype}) :<br> body)</code></pre><p>and the desired replacements :</p><pre><code>val replacements = [<br> `myfunction => `print-int<br> `args => nested $ [<br> [`arg => `x, `argtype => `Int]<br> [`arg => `y, `argtype => `String]<br> [`arg => `z, `argtype => `Char]]<br> `body => `(println(x))]</code></pre><p>Then the following call to <code>fill-template</code> :</p><pre><code>fill-template(form, replacements)</code></pre><p>will return the following replaced form :</p><pre><code>`(defn print-int (x:Int, y:String, z:Char) :<br> (println(x)))</code></pre><p>Note, specially, the syntax in the template when using a nested template replacement. If the replacement is a nested template, then the template form key <span style="font-style:italic;">must</span> have form :</p><pre><code>key{pattern ...}</code></pre><p>Note that the set of replacements used during each replacement of a nested template also includes all the entries from the parent replacements.</p><p>For example, if we use the following replacements on the same template form :</p><pre><code>val replacements = [<br> `myfunction => `print-int<br> `argtype => `Int<br> `args => nested $ [<br> [`arg => `x]<br> [`arg => `y]<br> [`arg => `z, `argtype => `Char]]<br> `body => `(println(x))]</code></pre><p>Then the call to <code>fill-template</code> :</p><pre><code>fill-template(form, replacements)</code></pre><p>will return the following replaced form :</p><pre><code>`(defn print-int (x:Int, y:Int, z:Char) :<br> (println(x)))</code></pre><p>Notice that the <code>`argtype</code> replacement value is inherited from the parent bindings.</p><h3 id="anchor645">Plural Template</h3><p>The plural template is similar to the nested template and allows for a pattern to be repeatedly replaced using a different set of replacements each time. The difference is that the plural template allows the user to specify <span style="font-style:italic;">for each symbol</span> what it should be replaced with each time, whereas the nested template requires the user to specify <span style="font-style:italic;">for each replacement</span> what the set of replacements should be.</p><p>The following function creates a plural template given a sequence of replacements, each replacement being a sequence itself. Note that the length of each replacement value must be equal.</p><pre><code>defn plural (entries: Seqable<KeyValue<Symbol, Seqable>>) -> PluralTemplate</code></pre><p>Consider the following template :</p><pre><code>val form = `(<br> defn myfunction (args{arg : argtype}) :<br> body)</code></pre><p>and the desired replacements :</p><pre><code>val replacements = [<br> `myfunction => `print-int<br> `args => plural $ [<br> `arg => `(x y z)<br> `argtype => `(Int String Char)]<br> `body => `(println(x))]</code></pre><p>Then the following call to <code>fill-template</code> :</p><pre><code>fill-template(form, replacements)</code></pre><p>will return the following replaced form :</p><pre><code>`(defn print-int (x:Int, y:String, z:Char) :<br> (println(x)))</code></pre><h3 id="anchor646">Choice Template</h3><p>The choice template allows for a symbol to be replaced with a pattern selected from amongst a list of patterns depending on the replacement value.</p><p>The following function creates a choice template given the choice <code>n</code>.</p><pre><code>defn choice (n:Int) -> ChoiceTemplate</code></pre><p>The following convenience function also allows for users to create a choice template given a boolean value, where <code>false</code> is equivalent to choice <code>0</code> and <code>true</code> is equivalent to choice <code>1</code>.</p><pre><code>defn choice (b:True|False) -> ChoiceTemplate</code></pre><p>Consider the following template :</p><pre><code>val form = `(<br> defn myfunction (x:Int) :<br> body{<br> println(x)<br> }{<br> x + 1<br> }{<br> fatal(x)<br> })</code></pre><p>and the desired replacements :</p><pre><code>val replacements = [<br> `myfunction => `print-int<br> `body => choice(1)]</code></pre><p>Then the following call to <code>fill-template</code> :</p><pre><code>fill-template(form, replacements)</code></pre><p>will return the following replaced form :</p><pre><code>`(defn print-int (x:Int) :<br> x + 1)</code></pre><p>Note, specially, the syntax in the template when using a choice template replacement. If the replacement is a choice template, then the template form key <span style="font-style:italic;">must</span> have form :</p><pre><code>key{pattern0 ...}{pattern1 ...}{pattern2 ...}</code></pre><p>We can select which pattern is produced by changing the index we use to create the choice template. The following replacements :</p><pre><code>val replacements = [<br> `myfunction => `print-int<br> `body => choice(2)]</code></pre><p>will result in the following replaced form :</p><pre><code>`(defn print-int (x:Int) :<br> fatal(x))</code></pre>
</td>
<td class="rest">
<img url="resources/spacer.gif"></img>
</td>
</tr>
<tr><td colspan="3" class="footer">
Site design by Luca Li. Copyright 2015.
</td></tr>
</table>
</body>
</html>