123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486 |
- <?xml version="1.0" encoding="utf-8" ?>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <!-- This file is generated by Nim. -->
- <html xmlns="https://www.w3.org/1999/xhtml" xml:lang="en" lang="en" data-theme="auto">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Nim Tutorial (Part II)</title>
- <!-- Google fonts -->
- <link href='https://fonts.googleapis.com/css?family=Lato:400,600,900' rel='stylesheet' type='text/css'/>
- <link href='https://fonts.googleapis.com/css?family=Source+Code+Pro:400,500,600' rel='stylesheet' type='text/css'/>
- <!-- Favicon -->
- <link rel="shortcut icon" href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAUAAAAF////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAIAAABbAAAAlQAAAKIAAACbAAAAmwAAAKIAAACVAAAAWwAAAAL///8A////AP///wD///8A////AAAAABQAAADAAAAAYwAAAA3///8A////AP///wD///8AAAAADQAAAGMAAADAAAAAFP///wD///8A////AP///wAAAACdAAAAOv///wD///8A////AP///wD///8A////AP///wD///8AAAAAOgAAAJ3///8A////AP///wAAAAAnAAAAcP///wAAAAAoAAAASv///wD///8A////AP///wAAAABKAAAAKP///wAAAABwAAAAJ////wD///8AAAAAgQAAABwAAACIAAAAkAAAAJMAAACtAAAAFQAAABUAAACtAAAAkwAAAJAAAACIAAAAHAAAAIH///8A////AAAAAKQAAACrAAAAaP///wD///8AAAAARQAAANIAAADSAAAARf///wD///8AAAAAaAAAAKsAAACk////AAAAADMAAACcAAAAnQAAABj///8A////AP///wAAAAAYAAAAGP///wD///8A////AAAAABgAAACdAAAAnAAAADMAAAB1AAAAwwAAAP8AAADpAAAAsQAAAE4AAAAb////AP///wAAAAAbAAAATgAAALEAAADpAAAA/wAAAMMAAAB1AAAAtwAAAOkAAAD/AAAA/wAAAP8AAADvAAAA3gAAAN4AAADeAAAA3gAAAO8AAAD/AAAA/wAAAP8AAADpAAAAtwAAAGUAAAA/AAAA3wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADfAAAAPwAAAGX///8A////AAAAAEgAAADtAAAAvwAAAL0AAADGAAAA7wAAAO8AAADGAAAAvQAAAL8AAADtAAAASP///wD///8A////AP///wD///8AAAAAO////wD///8A////AAAAAIcAAACH////AP///wD///8AAAAAO////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A//8AAP//AAD4HwAA7/cAAN/7AAD//wAAoYUAAJ55AACf+QAAh+EAAAAAAADAAwAA4AcAAP5/AAD//wAA//8AAA=="/>
- <link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4QQQEwksSS9ZWwAAAk1JREFUWMPtll2ITVEUx39nn/O7Y5qR8f05wtCUUr6ZIS++8pEnkZInPImneaCQ5METNdOkeFBKUhMPRIkHKfEuUZSUlGlKPN2TrgfncpvmnntnmlEyq1Z7t89/rf9a6+y99oZxGZf/XeIq61EdtgKXgdXA0xrYAvBjOIF1AI9zvjcC74BSpndrJPkBWDScTF8Aa4E3wDlgHbASaANmVqlcCnwHvgDvgVfAJ+AikAAvgfVZwLnSVZHZaOuKoQi3ZOMi4NkYkpe1p4J7A8BpYAD49hfIy/oqG0+hLomiKP2L5L+1ubn5115S+3OAn4EnwBlgMzCjyt6ZAnQCJ4A7wOs88iRJHvw50HoujuPBoCKwHWiosy8MdfZnAdcHk8dxXFJ3VQbQlCTJvRBCGdRbD4M6uc5glpY3eAihpN5S5w12diSEcCCEcKUO4ljdr15T76ur1FDDLIQQ3qv71EdDOe3Kxj3leRXyk+pxdWnFWod6Wt2bY3de3aSuUHcPBVimHs7mK9WrmeOF6lR1o9qnzskh2ar2qm1qizpfXaPeVGdlmGN5pb09qMxz1Xb1kLqgzn1RyH7JUXW52lr5e/Kqi9qpto7V1atuUzfnARrV7jEib1T76gG2qxdGmXyiekkt1GswPTtek0aBfJp6YySGBfWg2tPQ0FAYgf1stUfdmdcjarbYJEniKIq6gY/Aw+zWHAC+p2labGpqiorFYgGYCEzN7oQdQClN07O1/EfDyGgC0ALMBdYAi4FyK+4H3gLPsxfR1zRNi+NP7nH5J+QntnXe5B5mpfQAAAAASUVORK5CYII=">
- <!-- CSS -->
- <link rel="stylesheet" type="text/css" href="nimdoc.out.css?v=2.3.1">
- <!-- JS -->
- <script type="text/javascript" src="dochack.js?v=2.3.1"></script>
- </head>
- <body>
- <div class="document" id="documentId">
- <div class="container">
- <h1 class="title">Nim Tutorial (Part II)</h1>
- <div class="row">
- <div class="three columns">
- <div class="theme-select-wrapper">
- <label for="theme-select">Theme: </label>
- <select id="theme-select" onchange="setTheme(this.value)">
- <option value="auto">🌗 Match OS</option>
- <option value="dark">🌑 Dark</option>
- <option value="light">🌕 Light</option>
- </select>
- </div>
- <div id="global-links">
- <ul class="simple-boot">
- <li><a href="manual.html">Manual</a></li>
- <li><a href="lib.html">Standard library</a></li>
- <li> <a id="indexLink" href="theindex.html">Index</a></li>
- <li><a href="compiler/theindex.html">Compiler docs</a></li>
- <li><a href="https://nim-lang.github.io/fusion/theindex.html">Fusion docs</a></li>
- <li><a href="https://nim-lang.github.io/Nim/">devel</a>, <a href="https://nim-lang.org/documentation.html">stable</a></li>
- </ul>
- </div>
- <div id="searchInputDiv">
- Search: <input type="search" id="searchInput"
- oninput="search()" />
- </div>
- <div class="search-groupby">
- Group by:
- <select onchange="groupBy(this.value)">
- <option value="section">Section</option>
- <option value="type">Type</option>
- </select>
- </div>
- <ul class="simple simple-toc" id="toc-list">
- <li><a class="reference" id="introduction_toc" href="#introduction">Introduction</a></li>
- <li><a class="reference" id="pragmas_toc" href="#pragmas">Pragmas</a></li>
- <li><a class="reference" id="object-oriented-programming_toc" href="#object-oriented-programming">Object Oriented Programming</a></li>
- <ul class="simple"><li><a class="reference" id="object-oriented-programming-inheritance_toc" href="#object-oriented-programming-inheritance">Inheritance</a></li>
- <li><a class="reference" id="object-oriented-programming-mutually-recursive-types_toc" href="#object-oriented-programming-mutually-recursive-types">Mutually recursive types</a></li>
- <li><a class="reference" id="object-oriented-programming-type-conversions_toc" href="#object-oriented-programming-type-conversions">Type conversions</a></li>
- <li><a class="reference" id="object-oriented-programming-object-variants_toc" href="#object-oriented-programming-object-variants">Object variants</a></li>
- <li><a class="reference" id="object-oriented-programming-method-call-syntax_toc" href="#object-oriented-programming-method-call-syntax">Method call syntax</a></li>
- <li><a class="reference" id="object-oriented-programming-properties_toc" href="#object-oriented-programming-properties">Properties</a></li>
- <li><a class="reference" id="object-oriented-programming-dynamic-dispatch_toc" href="#object-oriented-programming-dynamic-dispatch">Dynamic dispatch</a></li>
- </ul><li><a class="reference" id="exceptions_toc" href="#exceptions">Exceptions</a></li>
- <ul class="simple"><li><a class="reference" id="exceptions-raise-statement_toc" href="#exceptions-raise-statement">Raise statement</a></li>
- <li><a class="reference" id="exceptions-try-statement_toc" href="#exceptions-try-statement">Try statement</a></li>
- <li><a class="reference" id="exceptions-annotating-procs-with-raised-exceptions_toc" href="#exceptions-annotating-procs-with-raised-exceptions">Annotating procs with raised exceptions</a></li>
- </ul><li><a class="reference" id="generics_toc" href="#generics">Generics</a></li>
- <li><a class="reference" id="templates_toc" href="#templates">Templates</a></li>
- <ul class="simple"><li><a class="reference" id="templates-examplecolon-lifting-procs_toc" href="#templates-examplecolon-lifting-procs">Example: Lifting Procs</a></li>
- </ul><li><a class="reference" id="compilation-to-javascript_toc" href="#compilation-to-javascript">Compilation to JavaScript</a></li>
- <li><a class="reference" id="part-3_toc" href="#part-3">Part 3</a></li>
- </ul>
- </div>
- <div class="nine columns" id="content">
- <a href="https://github.com/nim-lang/Nim/tree/devel/doc/tut2.md#L1" class="link-seesrc" target="_blank">Source</a>
- <a href="https://github.com/nim-lang/Nim/edit/devel/doc/tut2.md#L1" class="link-seesrc" target="_blank" >Edit</a>
- <div id="tocRoot"></div>
-
- <p class="module-desc"><table class="docinfo" frame="void" rules="none"><col class="docinfo-name" /><col class="docinfo-content" /><tbody valign="top"><tr><th class="docinfo-name">Author:</th><td>Andreas Rumpf</td></tr>
- <tr><th class="docinfo-name">Version:</th><td>2.3.1</td></tr>
- </tbody></table>
- <h1><a class="toc-backref" id="introduction" href="#introduction">Introduction</a></h1><blockquote class="markdown-quote"><p>"Repetition renders the ridiculous reasonable." -- Norman Wildberger</p></blockquote>
- <p>This document is a tutorial for the advanced constructs of the <em>Nim</em> programming language. <strong>Note that this document is somewhat obsolete as the</strong> <a class="reference external" href="manual.html">manual</a> <strong>contains many more examples of the advanced language features.</strong></p>
- <h1><a class="toc-backref" id="pragmas" href="#pragmas">Pragmas</a></h1><p>Pragmas are Nim's method to give the compiler additional information/ commands without introducing a massive number of new keywords. Pragmas are enclosed in the special <tt class="docutils literal"><span class="pre"><span class="Punctuation">{</span><span class="Operator">.</span></span></tt> and <tt class="docutils literal"><span class="pre"><span class="Operator">.</span><span class="Punctuation">}</span></span></tt> curly dot brackets. This tutorial does not cover pragmas. See the <a class="reference external" href="manual.html#pragmas">manual</a> or <a class="reference external" href=" nimc.html#additional-features">user guide</a> for a description of the available pragmas.</p>
- <h1><a class="toc-backref" id="object-oriented-programming" href="#object-oriented-programming">Object Oriented Programming</a></h1><p>While Nim's support for object oriented programming (OOP) is minimalistic, powerful OOP techniques can be used. OOP is seen as <em>one</em> way to design a program, not <em>the only</em> way. Often a procedural approach leads to simpler and more efficient code. In particular, preferring composition over inheritance is often the better design.</p>
- <h2><a class="toc-backref" id="object-oriented-programming-inheritance" href="#object-oriented-programming-inheritance">Inheritance</a></h2><p>Inheritance in Nim is entirely optional. To enable inheritance with runtime type information the object needs to inherit from <tt class="docutils literal"><span class="pre"><span class="Identifier">RootObj</span></span></tt>. This can be done directly, or indirectly by inheriting from an object that inherits from <tt class="docutils literal"><span class="pre"><span class="Identifier">RootObj</span></span></tt>. Usually types with inheritance are also marked as <tt class="docutils literal"><span class="pre"><span class="Keyword">ref</span></span></tt> types even though this isn't strictly enforced. To check at runtime if an object is of a certain type, the <tt class="docutils literal"><span class="pre"><span class="Keyword">of</span></span></tt> operator can be used.</p>
- <p><pre class="listing"><span class="Keyword">type</span>
- <span class="Identifier">Person</span> <span class="Operator">=</span> <span class="Keyword">ref</span> <span class="Keyword">object</span> <span class="Keyword">of</span> <span class="Identifier">RootObj</span>
- <span class="Identifier">name</span><span class="Operator">*:</span> <span class="Identifier">string</span> <span class="Comment"># the * means that `name` is accessible from other modules</span>
- <span class="Identifier">age</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Comment"># no * means that the field is hidden from other modules</span>
-
- <span class="Identifier">Student</span> <span class="Operator">=</span> <span class="Keyword">ref</span> <span class="Keyword">object</span> <span class="Keyword">of</span> <span class="Identifier">Person</span> <span class="Comment"># Student inherits from Person</span>
- <span class="Identifier">id</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Comment"># with an id field</span>
- <span class="Keyword">var</span>
- <span class="Identifier">student</span><span class="Punctuation">:</span> <span class="Identifier">Student</span>
- <span class="Identifier">person</span><span class="Punctuation">:</span> <span class="Identifier">Person</span>
- <span class="Identifier">assert</span><span class="Punctuation">(</span><span class="Identifier">student</span> <span class="Keyword">of</span> <span class="Identifier">Student</span><span class="Punctuation">)</span> <span class="Comment"># is true</span>
- <span class="Comment"># object construction:</span>
- <span class="Identifier">student</span> <span class="Operator">=</span> <span class="Identifier">Student</span><span class="Punctuation">(</span><span class="Identifier">name</span><span class="Punctuation">:</span> <span class="StringLit">"Anton"</span><span class="Punctuation">,</span> <span class="Identifier">age</span><span class="Punctuation">:</span> <span class="DecNumber">5</span><span class="Punctuation">,</span> <span class="Identifier">id</span><span class="Punctuation">:</span> <span class="DecNumber">2</span><span class="Punctuation">)</span>
- <span class="Identifier">echo</span> <span class="Identifier">student</span><span class="Punctuation">[</span><span class="Punctuation">]</span></pre></p>
- <p>Inheritance is done with the <tt class="docutils literal"><span class="pre"><span class="Keyword">object</span> <span class="Keyword">of</span></span></tt> syntax. Multiple inheritance is currently not supported. If an object type has no suitable ancestor, <tt class="docutils literal"><span class="pre"><span class="Identifier">RootObj</span></span></tt> can be used as its ancestor, but this is only a convention. Objects that have no ancestor are implicitly <tt class="docutils literal"><span class="pre"><span class="Identifier">final</span></span></tt>. You can use the <tt class="docutils literal"><span class="pre"><span class="Identifier">inheritable</span></span></tt> pragma to introduce new object roots apart from <tt class="docutils literal"><span class="pre"><span class="Identifier">system</span><span class="Operator">.</span><span class="Identifier">RootObj</span></span></tt>. (This is used in the GTK wrapper for instance.)</p>
- <p>Ref objects should be used whenever inheritance is used. It isn't strictly necessary, but with non-ref objects, assignments such as <tt class="docutils literal"><span class="pre"><span class="Keyword">let</span> <span class="Identifier">person</span><span class="Punctuation">:</span> <span class="Identifier">Person</span> <span class="Operator">=</span> <span class="Identifier">Student</span><span class="Punctuation">(</span><span class="Identifier">id</span><span class="Punctuation">:</span> <span class="DecNumber">123</span><span class="Punctuation">)</span></span></tt> will truncate subclass fields.</p>
- <p><strong>Note</strong>: Composition (<em>has-a</em> relation) is often preferable to inheritance (<em>is-a</em> relation) for simple code reuse. Since objects are value types in Nim, composition is as efficient as inheritance.</p>
- <h2><a class="toc-backref" id="object-oriented-programming-mutually-recursive-types" href="#object-oriented-programming-mutually-recursive-types">Mutually recursive types</a></h2><p>Objects, tuples and references can model quite complex data structures which depend on each other; they are <em>mutually recursive</em>. In Nim these types can only be declared within a single type section. (Anything else would require arbitrary symbol lookahead which slows down compilation.)</p>
- <p>Example:</p>
- <p><pre class="listing"><span class="Keyword">type</span>
- <span class="Identifier">Node</span> <span class="Operator">=</span> <span class="Keyword">ref</span> <span class="Keyword">object</span> <span class="Comment"># a reference to an object with the following field:</span>
- <span class="Identifier">le</span><span class="Punctuation">,</span> <span class="Identifier">ri</span><span class="Punctuation">:</span> <span class="Identifier">Node</span> <span class="Comment"># left and right subtrees</span>
- <span class="Identifier">sym</span><span class="Punctuation">:</span> <span class="Keyword">ref</span> <span class="Identifier">Sym</span> <span class="Comment"># leaves contain a reference to a Sym</span>
-
- <span class="Identifier">Sym</span> <span class="Operator">=</span> <span class="Keyword">object</span> <span class="Comment"># a symbol</span>
- <span class="Identifier">name</span><span class="Punctuation">:</span> <span class="Identifier">string</span> <span class="Comment"># the symbol's name</span>
- <span class="Identifier">line</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Comment"># the line the symbol was declared in</span>
- <span class="Identifier">code</span><span class="Punctuation">:</span> <span class="Identifier">Node</span> <span class="Comment"># the symbol's abstract syntax tree</span></pre></p>
- <h2><a class="toc-backref" id="object-oriented-programming-type-conversions" href="#object-oriented-programming-type-conversions">Type conversions</a></h2><p>Nim distinguishes between <span id="type-casts_1">type casts</span> and <span id="type-conversions_1">type conversions</span>. Casts are done with the <tt class="docutils literal"><span class="pre"><span class="Keyword">cast</span></span></tt> operator and force the compiler to interpret a bit pattern to be of another type.</p>
- <p>Type conversions are a much more polite way to convert a type into another: They preserve the abstract <em>value</em>, not necessarily the <em>bit-pattern</em>. If a type conversion is not possible, the compiler complains or an exception is raised.</p>
- <p>The syntax for type conversions is <tt class="docutils literal"><span class="pre"><span class="Identifier">destination_type</span><span class="Punctuation">(</span><span class="Identifier">expression_to_convert</span><span class="Punctuation">)</span></span></tt> (like an ordinary call):</p>
- <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">getID</span><span class="Punctuation">(</span><span class="Identifier">x</span><span class="Punctuation">:</span> <span class="Identifier">Person</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Operator">=</span>
- <span class="Identifier">Student</span><span class="Punctuation">(</span><span class="Identifier">x</span><span class="Punctuation">)</span><span class="Operator">.</span><span class="Identifier">id</span></pre></p>
- <p>The <tt class="docutils literal"><span class="pre"><span class="Identifier">InvalidObjectConversionDefect</span></span></tt> exception is raised if <tt class="docutils literal"><span class="pre"><span class="Identifier">x</span></span></tt> is not a <tt class="docutils literal"><span class="pre"><span class="Identifier">Student</span></span></tt>.</p>
- <h2><a class="toc-backref" id="object-oriented-programming-object-variants" href="#object-oriented-programming-object-variants">Object variants</a></h2><p>Often an object hierarchy is overkill in certain situations where simple variant types are needed.</p>
- <p>An example:</p>
- <p><pre class="listing"><span class="Comment"># This is an example how an abstract syntax tree could be modelled in Nim</span>
- <span class="Keyword">type</span>
- <span class="Identifier">NodeKind</span> <span class="Operator">=</span> <span class="Keyword">enum</span> <span class="Comment"># the different node types</span>
- <span class="Identifier">nkInt</span><span class="Punctuation">,</span> <span class="Comment"># a leaf with an integer value</span>
- <span class="Identifier">nkFloat</span><span class="Punctuation">,</span> <span class="Comment"># a leaf with a float value</span>
- <span class="Identifier">nkString</span><span class="Punctuation">,</span> <span class="Comment"># a leaf with a string value</span>
- <span class="Identifier">nkAdd</span><span class="Punctuation">,</span> <span class="Comment"># an addition</span>
- <span class="Identifier">nkSub</span><span class="Punctuation">,</span> <span class="Comment"># a subtraction</span>
- <span class="Identifier">nkIf</span> <span class="Comment"># an if statement</span>
- <span class="Identifier">Node</span> <span class="Operator">=</span> <span class="Keyword">ref</span> <span class="Keyword">object</span>
- <span class="Keyword">case</span> <span class="Identifier">kind</span><span class="Punctuation">:</span> <span class="Identifier">NodeKind</span> <span class="Comment"># the `kind` field is the discriminator</span>
- <span class="Keyword">of</span> <span class="Identifier">nkInt</span><span class="Punctuation">:</span> <span class="Identifier">intVal</span><span class="Punctuation">:</span> <span class="Identifier">int</span>
- <span class="Keyword">of</span> <span class="Identifier">nkFloat</span><span class="Punctuation">:</span> <span class="Identifier">floatVal</span><span class="Punctuation">:</span> <span class="Identifier">float</span>
- <span class="Keyword">of</span> <span class="Identifier">nkString</span><span class="Punctuation">:</span> <span class="Identifier">strVal</span><span class="Punctuation">:</span> <span class="Identifier">string</span>
- <span class="Keyword">of</span> <span class="Identifier">nkAdd</span><span class="Punctuation">,</span> <span class="Identifier">nkSub</span><span class="Punctuation">:</span>
- <span class="Identifier">leftOp</span><span class="Punctuation">,</span> <span class="Identifier">rightOp</span><span class="Punctuation">:</span> <span class="Identifier">Node</span>
- <span class="Keyword">of</span> <span class="Identifier">nkIf</span><span class="Punctuation">:</span>
- <span class="Identifier">condition</span><span class="Punctuation">,</span> <span class="Identifier">thenPart</span><span class="Punctuation">,</span> <span class="Identifier">elsePart</span><span class="Punctuation">:</span> <span class="Identifier">Node</span>
- <span class="Keyword">var</span> <span class="Identifier">n</span> <span class="Operator">=</span> <span class="Identifier">Node</span><span class="Punctuation">(</span><span class="Identifier">kind</span><span class="Punctuation">:</span> <span class="Identifier">nkFloat</span><span class="Punctuation">,</span> <span class="Identifier">floatVal</span><span class="Punctuation">:</span> <span class="FloatNumber">1.0</span><span class="Punctuation">)</span>
- <span class="Comment"># the following statement raises an `FieldDefect` exception, because</span>
- <span class="Comment"># n.kind's value does not fit:</span>
- <span class="Identifier">n</span><span class="Operator">.</span><span class="Identifier">strVal</span> <span class="Operator">=</span> <span class="StringLit">""</span></pre></p>
- <p>As can be seen from the example, an advantage to an object hierarchy is that no conversion between different object types is needed. Yet, access to invalid object fields raises an exception.</p>
- <h2><a class="toc-backref" id="object-oriented-programming-method-call-syntax" href="#object-oriented-programming-method-call-syntax">Method call syntax</a></h2><p>There is a syntactic sugar for calling routines: The syntax <tt class="docutils literal"><span class="pre"><span class="Identifier">obj</span><span class="Operator">.</span><span class="Identifier">methodName</span><span class="Punctuation">(</span><span class="Identifier">args</span><span class="Punctuation">)</span></span></tt> can be used instead of <tt class="docutils literal"><span class="pre"><span class="Identifier">methodName</span><span class="Punctuation">(</span><span class="Identifier">obj</span><span class="Punctuation">,</span> <span class="Identifier">args</span><span class="Punctuation">)</span></span></tt>. If there are no remaining arguments, the parentheses can be omitted: <tt class="docutils literal"><span class="pre"><span class="Identifier">obj</span><span class="Operator">.</span><span class="Identifier">len</span></span></tt> (instead of <tt class="docutils literal"><span class="pre"><span class="Identifier">len</span><span class="Punctuation">(</span><span class="Identifier">obj</span><span class="Punctuation">)</span></span></tt>).</p>
- <p>This method call syntax is not restricted to objects, it can be used for any type:</p>
- <p><pre class="listing"><span class="Keyword">import</span> <span class="Identifier">std</span><span class="Operator">/</span><span class="Identifier">strutils</span>
- <span class="Identifier">echo</span> <span class="StringLit">"abc"</span><span class="Operator">.</span><span class="Identifier">len</span> <span class="Comment"># is the same as echo len("abc")</span>
- <span class="Identifier">echo</span> <span class="StringLit">"abc"</span><span class="Operator">.</span><span class="Identifier">toUpperAscii</span><span class="Punctuation">(</span><span class="Punctuation">)</span>
- <span class="Identifier">echo</span><span class="Punctuation">(</span><span class="Punctuation">{</span><span class="Punctuation">'</span><span class="Identifier">a</span><span class="CharLit">', '</span><span class="Identifier">b</span><span class="CharLit">', '</span><span class="Identifier">c</span><span class="CharLit">'}.card)</span>
- <span class="Identifier">stdout</span><span class="Operator">.</span><span class="Identifier">writeLine</span><span class="Punctuation">(</span><span class="StringLit">"Hallo"</span><span class="Punctuation">)</span> <span class="Comment"># the same as writeLine(stdout, "Hallo")</span></pre></p>
- <p>(Another way to look at the method call syntax is that it provides the missing postfix notation.)</p>
- <p>So "pure object oriented" code is easy to write:</p>
- <p><pre class="listing"><span class="Keyword">import</span> <span class="Identifier">std</span><span class="Operator">/</span><span class="Punctuation">[</span><span class="Identifier">strutils</span><span class="Punctuation">,</span> <span class="Identifier">sequtils</span><span class="Punctuation">]</span>
- <span class="Identifier">stdout</span><span class="Operator">.</span><span class="Identifier">writeLine</span><span class="Punctuation">(</span><span class="StringLit">"Give a list of numbers (separated by spaces): "</span><span class="Punctuation">)</span>
- <span class="Identifier">stdout</span><span class="Operator">.</span><span class="Identifier">write</span><span class="Punctuation">(</span><span class="Identifier">stdin</span><span class="Operator">.</span><span class="Identifier">readLine</span><span class="Operator">.</span><span class="Identifier">splitWhitespace</span><span class="Operator">.</span><span class="Identifier">map</span><span class="Punctuation">(</span><span class="Identifier">parseInt</span><span class="Punctuation">)</span><span class="Operator">.</span><span class="Identifier">max</span><span class="Operator">.</span><span class="Punctuation">`</span><span class="Operator">$</span><span class="Punctuation">`</span><span class="Punctuation">)</span>
- <span class="Identifier">stdout</span><span class="Operator">.</span><span class="Identifier">writeLine</span><span class="Punctuation">(</span><span class="StringLit">" is the maximum!"</span><span class="Punctuation">)</span></pre></p>
- <h2><a class="toc-backref" id="object-oriented-programming-properties" href="#object-oriented-programming-properties">Properties</a></h2><p>As the above example shows, Nim has no need for <em>get-properties</em>: Ordinary get-procedures that are called with the <em>method call syntax</em> achieve the same. But setting a value is different; for this a special setter syntax is needed:</p>
- <p><pre class="listing"><span class="Keyword">type</span>
- <span class="Identifier">Socket</span><span class="Operator">*</span> <span class="Operator">=</span> <span class="Keyword">ref</span> <span class="Keyword">object</span> <span class="Keyword">of</span> <span class="Identifier">RootObj</span>
- <span class="Identifier">h</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Comment"># cannot be accessed from the outside of the module due to missing star</span>
- <span class="Keyword">proc</span> <span class="Punctuation">`</span><span class="Identifier">host</span><span class="Operator">=</span><span class="Punctuation">`</span><span class="Operator">*</span><span class="Punctuation">(</span><span class="Identifier">s</span><span class="Punctuation">:</span> <span class="Keyword">var</span> <span class="Identifier">Socket</span><span class="Punctuation">,</span> <span class="Identifier">value</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">)</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">inline</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Operator">=</span>
- <span class="Comment">## setter of host address</span>
- <span class="Identifier">s</span><span class="Operator">.</span><span class="Identifier">h</span> <span class="Operator">=</span> <span class="Identifier">value</span>
- <span class="Keyword">proc</span> <span class="Identifier">host</span><span class="Operator">*</span><span class="Punctuation">(</span><span class="Identifier">s</span><span class="Punctuation">:</span> <span class="Identifier">Socket</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">inline</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Operator">=</span>
- <span class="Comment">## getter of host address</span>
- <span class="Identifier">s</span><span class="Operator">.</span><span class="Identifier">h</span>
- <span class="Keyword">var</span> <span class="Identifier">s</span><span class="Punctuation">:</span> <span class="Identifier">Socket</span>
- <span class="Identifier">new</span> <span class="Identifier">s</span>
- <span class="Identifier">s</span><span class="Operator">.</span><span class="Identifier">host</span> <span class="Operator">=</span> <span class="DecNumber">34</span> <span class="Comment"># same as `host=`(s, 34)</span></pre></p>
- <p>(The example also shows <tt class="docutils literal"><span class="pre"><span class="Identifier">inline</span></span></tt> procedures.)</p>
- <p>The <tt class="docutils literal"><span class="pre"><span class="Punctuation">[</span><span class="Punctuation">]</span></span></tt> array access operator can be overloaded to provide <span id="array-properties_1">array properties</span>:</p>
- <p><pre class="listing"><span class="Keyword">type</span>
- <span class="Identifier">Vector</span><span class="Operator">*</span> <span class="Operator">=</span> <span class="Keyword">object</span>
- <span class="Identifier">x</span><span class="Punctuation">,</span> <span class="Identifier">y</span><span class="Punctuation">,</span> <span class="Identifier">z</span><span class="Punctuation">:</span> <span class="Identifier">float</span>
- <span class="Keyword">proc</span> <span class="Punctuation">`</span><span class="Punctuation">[</span><span class="Punctuation">]</span><span class="Operator">=</span><span class="Punctuation">`</span><span class="Operator">*</span> <span class="Punctuation">(</span><span class="Identifier">v</span><span class="Punctuation">:</span> <span class="Keyword">var</span> <span class="Identifier">Vector</span><span class="Punctuation">,</span> <span class="Identifier">i</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">,</span> <span class="Identifier">value</span><span class="Punctuation">:</span> <span class="Identifier">float</span><span class="Punctuation">)</span> <span class="Operator">=</span>
- <span class="Comment"># setter</span>
- <span class="Keyword">case</span> <span class="Identifier">i</span>
- <span class="Keyword">of</span> <span class="DecNumber">0</span><span class="Punctuation">:</span> <span class="Identifier">v</span><span class="Operator">.</span><span class="Identifier">x</span> <span class="Operator">=</span> <span class="Identifier">value</span>
- <span class="Keyword">of</span> <span class="DecNumber">1</span><span class="Punctuation">:</span> <span class="Identifier">v</span><span class="Operator">.</span><span class="Identifier">y</span> <span class="Operator">=</span> <span class="Identifier">value</span>
- <span class="Keyword">of</span> <span class="DecNumber">2</span><span class="Punctuation">:</span> <span class="Identifier">v</span><span class="Operator">.</span><span class="Identifier">z</span> <span class="Operator">=</span> <span class="Identifier">value</span>
- <span class="Keyword">else</span><span class="Punctuation">:</span> <span class="Identifier">assert</span><span class="Punctuation">(</span><span class="Identifier">false</span><span class="Punctuation">)</span>
- <span class="Keyword">proc</span> <span class="Punctuation">`</span><span class="Punctuation">[</span><span class="Punctuation">]</span><span class="Punctuation">`</span><span class="Operator">*</span> <span class="Punctuation">(</span><span class="Identifier">v</span><span class="Punctuation">:</span> <span class="Identifier">Vector</span><span class="Punctuation">,</span> <span class="Identifier">i</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">float</span> <span class="Operator">=</span>
- <span class="Comment"># getter</span>
- <span class="Keyword">case</span> <span class="Identifier">i</span>
- <span class="Keyword">of</span> <span class="DecNumber">0</span><span class="Punctuation">:</span> <span class="Identifier">result</span> <span class="Operator">=</span> <span class="Identifier">v</span><span class="Operator">.</span><span class="Identifier">x</span>
- <span class="Keyword">of</span> <span class="DecNumber">1</span><span class="Punctuation">:</span> <span class="Identifier">result</span> <span class="Operator">=</span> <span class="Identifier">v</span><span class="Operator">.</span><span class="Identifier">y</span>
- <span class="Keyword">of</span> <span class="DecNumber">2</span><span class="Punctuation">:</span> <span class="Identifier">result</span> <span class="Operator">=</span> <span class="Identifier">v</span><span class="Operator">.</span><span class="Identifier">z</span>
- <span class="Keyword">else</span><span class="Punctuation">:</span> <span class="Identifier">assert</span><span class="Punctuation">(</span><span class="Identifier">false</span><span class="Punctuation">)</span></pre></p>
- <p>The example is silly, since a vector is better modelled by a tuple which already provides <tt class="docutils literal"><span class="pre"><span class="Identifier">v</span><span class="Punctuation">[</span><span class="Punctuation">]</span></span></tt> access.</p>
- <h2><a class="toc-backref" id="object-oriented-programming-dynamic-dispatch" href="#object-oriented-programming-dynamic-dispatch">Dynamic dispatch</a></h2><p>Procedures always use static dispatch. For dynamic dispatch replace the <tt class="docutils literal"><span class="pre"><span class="Keyword">proc</span></span></tt> keyword by <tt class="docutils literal"><span class="pre"><span class="Keyword">method</span></span></tt>:</p>
- <p><pre class="listing"><span class="Keyword">type</span>
- <span class="Identifier">Expression</span> <span class="Operator">=</span> <span class="Keyword">ref</span> <span class="Keyword">object</span> <span class="Keyword">of</span> <span class="Identifier">RootObj</span> <span class="Comment">## abstract base class for an expression</span>
- <span class="Identifier">Literal</span> <span class="Operator">=</span> <span class="Keyword">ref</span> <span class="Keyword">object</span> <span class="Keyword">of</span> <span class="Identifier">Expression</span>
- <span class="Identifier">x</span><span class="Punctuation">:</span> <span class="Identifier">int</span>
- <span class="Identifier">PlusExpr</span> <span class="Operator">=</span> <span class="Keyword">ref</span> <span class="Keyword">object</span> <span class="Keyword">of</span> <span class="Identifier">Expression</span>
- <span class="Identifier">a</span><span class="Punctuation">,</span> <span class="Identifier">b</span><span class="Punctuation">:</span> <span class="Identifier">Expression</span>
- <span class="Comment"># watch out: 'eval' relies on dynamic binding</span>
- <span class="Keyword">method</span> <span class="Identifier">eval</span><span class="Punctuation">(</span><span class="Identifier">e</span><span class="Punctuation">:</span> <span class="Identifier">Expression</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">base</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Operator">=</span>
- <span class="Comment"># override this base method</span>
- <span class="Identifier">quit</span> <span class="StringLit">"to override!"</span>
- <span class="Keyword">method</span> <span class="Identifier">eval</span><span class="Punctuation">(</span><span class="Identifier">e</span><span class="Punctuation">:</span> <span class="Identifier">Literal</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Operator">=</span> <span class="Identifier">e</span><span class="Operator">.</span><span class="Identifier">x</span>
- <span class="Keyword">method</span> <span class="Identifier">eval</span><span class="Punctuation">(</span><span class="Identifier">e</span><span class="Punctuation">:</span> <span class="Identifier">PlusExpr</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Operator">=</span> <span class="Identifier">eval</span><span class="Punctuation">(</span><span class="Identifier">e</span><span class="Operator">.</span><span class="Identifier">a</span><span class="Punctuation">)</span> <span class="Operator">+</span> <span class="Identifier">eval</span><span class="Punctuation">(</span><span class="Identifier">e</span><span class="Operator">.</span><span class="Identifier">b</span><span class="Punctuation">)</span>
- <span class="Keyword">proc</span> <span class="Identifier">newLit</span><span class="Punctuation">(</span><span class="Identifier">x</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">Literal</span> <span class="Operator">=</span> <span class="Identifier">Literal</span><span class="Punctuation">(</span><span class="Identifier">x</span><span class="Punctuation">:</span> <span class="Identifier">x</span><span class="Punctuation">)</span>
- <span class="Keyword">proc</span> <span class="Identifier">newPlus</span><span class="Punctuation">(</span><span class="Identifier">a</span><span class="Punctuation">,</span> <span class="Identifier">b</span><span class="Punctuation">:</span> <span class="Identifier">Expression</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">PlusExpr</span> <span class="Operator">=</span> <span class="Identifier">PlusExpr</span><span class="Punctuation">(</span><span class="Identifier">a</span><span class="Punctuation">:</span> <span class="Identifier">a</span><span class="Punctuation">,</span> <span class="Identifier">b</span><span class="Punctuation">:</span> <span class="Identifier">b</span><span class="Punctuation">)</span>
- <span class="Identifier">echo</span> <span class="Identifier">eval</span><span class="Punctuation">(</span><span class="Identifier">newPlus</span><span class="Punctuation">(</span><span class="Identifier">newPlus</span><span class="Punctuation">(</span><span class="Identifier">newLit</span><span class="Punctuation">(</span><span class="DecNumber">1</span><span class="Punctuation">)</span><span class="Punctuation">,</span> <span class="Identifier">newLit</span><span class="Punctuation">(</span><span class="DecNumber">2</span><span class="Punctuation">)</span><span class="Punctuation">)</span><span class="Punctuation">,</span> <span class="Identifier">newLit</span><span class="Punctuation">(</span><span class="DecNumber">4</span><span class="Punctuation">)</span><span class="Punctuation">)</span><span class="Punctuation">)</span></pre></p>
- <p>Note that in the example the constructors <tt class="docutils literal"><span class="pre"><span class="Identifier">newLit</span></span></tt> and <tt class="docutils literal"><span class="pre"><span class="Identifier">newPlus</span></span></tt> are procs because it makes more sense for them to use static binding, but <tt class="docutils literal"><span class="pre"><span class="Identifier">eval</span></span></tt> is a method because it requires dynamic binding.</p>
- <p><strong>Note:</strong> Starting from Nim 0.20, to use multi-methods one must explicitly pass <tt class="docutils literal"><span class="pre">--multimethods:on</span></tt> when compiling.</p>
- <p>In a multi-method all parameters that have an object type are used for the dispatching:</p>
- <p><pre class="listing"><span class="Keyword">type</span>
- <span class="Identifier">Thing</span> <span class="Operator">=</span> <span class="Keyword">ref</span> <span class="Keyword">object</span> <span class="Keyword">of</span> <span class="Identifier">RootObj</span>
- <span class="Identifier">Unit</span> <span class="Operator">=</span> <span class="Keyword">ref</span> <span class="Keyword">object</span> <span class="Keyword">of</span> <span class="Identifier">Thing</span>
- <span class="Identifier">x</span><span class="Punctuation">:</span> <span class="Identifier">int</span>
- <span class="Keyword">method</span> <span class="Identifier">collide</span><span class="Punctuation">(</span><span class="Identifier">a</span><span class="Punctuation">,</span> <span class="Identifier">b</span><span class="Punctuation">:</span> <span class="Identifier">Thing</span><span class="Punctuation">)</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">inline</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Operator">=</span>
- <span class="Identifier">quit</span> <span class="StringLit">"to override!"</span>
- <span class="Keyword">method</span> <span class="Identifier">collide</span><span class="Punctuation">(</span><span class="Identifier">a</span><span class="Punctuation">:</span> <span class="Identifier">Thing</span><span class="Punctuation">,</span> <span class="Identifier">b</span><span class="Punctuation">:</span> <span class="Identifier">Unit</span><span class="Punctuation">)</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">inline</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Operator">=</span>
- <span class="Identifier">echo</span> <span class="StringLit">"1"</span>
- <span class="Keyword">method</span> <span class="Identifier">collide</span><span class="Punctuation">(</span><span class="Identifier">a</span><span class="Punctuation">:</span> <span class="Identifier">Unit</span><span class="Punctuation">,</span> <span class="Identifier">b</span><span class="Punctuation">:</span> <span class="Identifier">Thing</span><span class="Punctuation">)</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">inline</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Operator">=</span>
- <span class="Identifier">echo</span> <span class="StringLit">"2"</span>
- <span class="Keyword">var</span> <span class="Identifier">a</span><span class="Punctuation">,</span> <span class="Identifier">b</span><span class="Punctuation">:</span> <span class="Identifier">Unit</span>
- <span class="Identifier">new</span> <span class="Identifier">a</span>
- <span class="Identifier">new</span> <span class="Identifier">b</span>
- <span class="Identifier">collide</span><span class="Punctuation">(</span><span class="Identifier">a</span><span class="Punctuation">,</span> <span class="Identifier">b</span><span class="Punctuation">)</span> <span class="Comment"># output: 2</span></pre></p>
- <p>As the example demonstrates, invocation of a multi-method cannot be ambiguous: Collide 2 is preferred over collide 1 because the resolution works from left to right. Thus <tt class="docutils literal"><span class="pre"><span class="Identifier">Unit</span><span class="Punctuation">,</span> <span class="Identifier">Thing</span></span></tt> is preferred over <tt class="docutils literal"><span class="pre"><span class="Identifier">Thing</span><span class="Punctuation">,</span> <span class="Identifier">Unit</span></span></tt>.</p>
- <p><strong>Performance note</strong>: Nim does not produce a virtual method table, but generates dispatch trees. This avoids the expensive indirect branch for method calls and enables inlining. However, other optimizations like compile time evaluation or dead code elimination do not work with methods.</p>
- <h1><a class="toc-backref" id="exceptions" href="#exceptions">Exceptions</a></h1><p>In Nim exceptions are objects. By convention, exception types are suffixed with 'Error'. The <a class="reference external" href="system.html">system</a> module defines an exception hierarchy that you might want to stick to. Exceptions derive from <tt class="docutils literal"><span class="pre"><span class="Identifier">system</span><span class="Operator">.</span><span class="Identifier">Exception</span></span></tt>, which provides the common interface.</p>
- <p>Exceptions have to be allocated on the heap because their lifetime is unknown. The compiler will prevent you from raising an exception created on the stack. All raised exceptions should at least specify the reason for being raised in the <tt class="docutils literal"><span class="pre"><span class="Identifier">msg</span></span></tt> field.</p>
- <p>A convention is that exceptions should be raised in <em>exceptional</em> cases, they should not be used as an alternative method of control flow.</p>
- <h2><a class="toc-backref" id="exceptions-raise-statement" href="#exceptions-raise-statement">Raise statement</a></h2><p>Raising an exception is done with the <tt class="docutils literal"><span class="pre"><span class="Keyword">raise</span></span></tt> statement:</p>
- <p><pre class="listing"><span class="Keyword">var</span>
- <span class="Identifier">e</span><span class="Punctuation">:</span> <span class="Keyword">ref</span> <span class="Identifier">OSError</span>
- <span class="Identifier">new</span><span class="Punctuation">(</span><span class="Identifier">e</span><span class="Punctuation">)</span>
- <span class="Identifier">e</span><span class="Operator">.</span><span class="Identifier">msg</span> <span class="Operator">=</span> <span class="StringLit">"the request to the OS failed"</span>
- <span class="Keyword">raise</span> <span class="Identifier">e</span></pre></p>
- <p>If the <tt class="docutils literal"><span class="pre"><span class="Keyword">raise</span></span></tt> keyword is not followed by an expression, the last exception is <em>re-raised</em>. For the purpose of avoiding repeating this common code pattern, the template <tt class="docutils literal"><span class="pre"><span class="Identifier">newException</span></span></tt> in the <tt class="docutils literal"><span class="pre"><span class="Identifier">system</span></span></tt> module can be used:</p>
- <p><pre class="listing"><span class="Keyword">raise</span> <span class="Identifier">newException</span><span class="Punctuation">(</span><span class="Identifier">OSError</span><span class="Punctuation">,</span> <span class="StringLit">"the request to the OS failed"</span><span class="Punctuation">)</span></pre></p>
- <h2><a class="toc-backref" id="exceptions-try-statement" href="#exceptions-try-statement">Try statement</a></h2><p>The <tt class="docutils literal"><span class="pre"><span class="Keyword">try</span></span></tt> statement handles exceptions:</p>
- <p><pre class="listing"><span class="Keyword">from</span> <span class="Identifier">std</span><span class="Operator">/</span><span class="Identifier">strutils</span> <span class="Keyword">import</span> <span class="Identifier">parseInt</span>
- <span class="Comment"># read the first two lines of a text file that should contain numbers</span>
- <span class="Comment"># and tries to add them</span>
- <span class="Keyword">var</span>
- <span class="Identifier">f</span><span class="Punctuation">:</span> <span class="Identifier">File</span>
- <span class="Keyword">if</span> <span class="Identifier">open</span><span class="Punctuation">(</span><span class="Identifier">f</span><span class="Punctuation">,</span> <span class="StringLit">"numbers.txt"</span><span class="Punctuation">)</span><span class="Punctuation">:</span>
- <span class="Keyword">try</span><span class="Punctuation">:</span>
- <span class="Keyword">let</span> <span class="Identifier">a</span> <span class="Operator">=</span> <span class="Identifier">readLine</span><span class="Punctuation">(</span><span class="Identifier">f</span><span class="Punctuation">)</span>
- <span class="Keyword">let</span> <span class="Identifier">b</span> <span class="Operator">=</span> <span class="Identifier">readLine</span><span class="Punctuation">(</span><span class="Identifier">f</span><span class="Punctuation">)</span>
- <span class="Identifier">echo</span> <span class="StringLit">"sum: "</span><span class="Punctuation">,</span> <span class="Identifier">parseInt</span><span class="Punctuation">(</span><span class="Identifier">a</span><span class="Punctuation">)</span> <span class="Operator">+</span> <span class="Identifier">parseInt</span><span class="Punctuation">(</span><span class="Identifier">b</span><span class="Punctuation">)</span>
- <span class="Keyword">except</span> <span class="Identifier">OverflowDefect</span><span class="Punctuation">:</span>
- <span class="Identifier">echo</span> <span class="StringLit">"overflow!"</span>
- <span class="Keyword">except</span> <span class="Identifier">ValueError</span><span class="Punctuation">:</span>
- <span class="Identifier">echo</span> <span class="StringLit">"could not convert string to integer"</span>
- <span class="Keyword">except</span> <span class="Identifier">IOError</span><span class="Punctuation">:</span>
- <span class="Identifier">echo</span> <span class="StringLit">"IO error!"</span>
- <span class="Keyword">except</span> <span class="Identifier">CatchableError</span><span class="Punctuation">:</span>
- <span class="Identifier">echo</span> <span class="StringLit">"Unknown exception!"</span>
- <span class="Comment"># reraise the unknown exception:</span>
- <span class="Keyword">raise</span>
- <span class="Keyword">finally</span><span class="Punctuation">:</span>
- <span class="Identifier">close</span><span class="Punctuation">(</span><span class="Identifier">f</span><span class="Punctuation">)</span></pre></p>
- <p>The statements after the <tt class="docutils literal"><span class="pre"><span class="Keyword">try</span></span></tt> are executed unless an exception is raised. Then the appropriate <tt class="docutils literal"><span class="pre"><span class="Keyword">except</span></span></tt> part is executed.</p>
- <p>The empty <tt class="docutils literal"><span class="pre"><span class="Keyword">except</span></span></tt> part is executed if there is an exception that is not explicitly listed. It is similar to an <tt class="docutils literal"><span class="pre"><span class="Keyword">else</span></span></tt> part in <tt class="docutils literal"><span class="pre"><span class="Keyword">if</span></span></tt> statements.</p>
- <p>If there is a <tt class="docutils literal"><span class="pre"><span class="Keyword">finally</span></span></tt> part, it is always executed after the exception handlers.</p>
- <p>The exception is <em>consumed</em> in an <tt class="docutils literal"><span class="pre"><span class="Keyword">except</span></span></tt> part. If an exception is not handled, it is propagated through the call stack. This means that often the rest of the procedure - that is not within a <tt class="docutils literal"><span class="pre"><span class="Keyword">finally</span></span></tt> clause - is not executed (if an exception occurs).</p>
- <p>If you need to <em>access</em> the actual exception object or message inside an <tt class="docutils literal"><span class="pre"><span class="Keyword">except</span></span></tt> branch you can use the <a class="reference external" href=" system.html#getCurrentException">getCurrentException()</a> and <a class="reference external" href=" system.html#getCurrentExceptionMsg">getCurrentExceptionMsg()</a> procs from the <a class="reference external" href="system.html">system</a> module. Example:</p>
- <p><pre class="listing"><span class="Keyword">try</span><span class="Punctuation">:</span>
- <span class="Identifier">doSomethingHere</span><span class="Punctuation">(</span><span class="Punctuation">)</span>
- <span class="Keyword">except</span> <span class="Identifier">CatchableError</span><span class="Punctuation">:</span>
- <span class="Keyword">let</span>
- <span class="Identifier">e</span> <span class="Operator">=</span> <span class="Identifier">getCurrentException</span><span class="Punctuation">(</span><span class="Punctuation">)</span>
- <span class="Identifier">msg</span> <span class="Operator">=</span> <span class="Identifier">getCurrentExceptionMsg</span><span class="Punctuation">(</span><span class="Punctuation">)</span>
- <span class="Identifier">echo</span> <span class="StringLit">"Got exception "</span><span class="Punctuation">,</span> <span class="Identifier">repr</span><span class="Punctuation">(</span><span class="Identifier">e</span><span class="Punctuation">)</span><span class="Punctuation">,</span> <span class="StringLit">" with message "</span><span class="Punctuation">,</span> <span class="Identifier">msg</span></pre></p>
- <h2><a class="toc-backref" id="exceptions-annotating-procs-with-raised-exceptions" href="#exceptions-annotating-procs-with-raised-exceptions">Annotating procs with raised exceptions</a></h2><p>Through the use of the optional <tt class="docutils literal"><span class="pre"><span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">raises</span><span class="Operator">.</span><span class="Punctuation">}</span></span></tt> pragma you can specify that a proc is meant to raise a specific set of exceptions, or none at all. If the <tt class="docutils literal"><span class="pre"><span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">raises</span><span class="Operator">.</span><span class="Punctuation">}</span></span></tt> pragma is used, the compiler will verify that this is true. For instance, if you specify that a proc raises <tt class="docutils literal"><span class="pre"><span class="Identifier">IOError</span></span></tt>, and at some point it (or one of the procs it calls) starts raising a new exception the compiler will prevent that proc from compiling. Usage example:</p>
- <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">complexProc</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">raises</span><span class="Punctuation">:</span> <span class="Punctuation">[</span><span class="Identifier">IOError</span><span class="Punctuation">,</span> <span class="Identifier">ArithmeticDefect</span><span class="Punctuation">]</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Operator">=</span>
- <span class="Operator">...</span>
- <span class="Keyword">proc</span> <span class="Identifier">simpleProc</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">raises</span><span class="Punctuation">:</span> <span class="Punctuation">[</span><span class="Punctuation">]</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Operator">=</span>
- <span class="Operator">...</span></pre></p>
- <p>Once you have code like this in place, if the list of raised exception changes the compiler will stop with an error specifying the line of the proc which stopped validating the pragma and the raised exception not being caught, along with the file and line where the uncaught exception is being raised, which may help you locate the offending code which has changed.</p>
- <p>If you want to add the <tt class="docutils literal"><span class="pre"><span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">raises</span><span class="Operator">.</span><span class="Punctuation">}</span></span></tt> pragma to existing code, the compiler can also help you. You can add the <tt class="docutils literal"><span class="pre"><span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">effects</span><span class="Operator">.</span><span class="Punctuation">}</span></span></tt> pragma statement to your proc and the compiler will output all inferred effects up to that point (exception tracking is part of Nim's effect system). Another more roundabout way to find out the list of exceptions raised by a proc is to use the Nim <tt class="docutils literal"><span class="pre">doc</span></tt> command which generates documentation for a whole module and decorates all procs with the list of raised exceptions. You can read more about Nim's <a class="reference external" href="manual.html#effect-system">effect system and related pragmas in the manual</a>.</p>
- <h1><a class="toc-backref" id="generics" href="#generics">Generics</a></h1><p>Generics are Nim's means to parametrize procs, iterators or types with <span id="type-parameters_1">type parameters</span>. Generic parameters are written within square brackets, for example <tt class="docutils literal"><span class="pre"><span class="Identifier">Foo</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span></span></tt>. They are most useful for efficient type safe containers:</p>
- <p><pre class="listing"><span class="Keyword">type</span>
- <span class="Identifier">BinaryTree</span><span class="Operator">*</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span> <span class="Operator">=</span> <span class="Keyword">ref</span> <span class="Keyword">object</span> <span class="Comment"># BinaryTree is a generic type with</span>
- <span class="Comment"># generic param `T`</span>
- <span class="Identifier">le</span><span class="Punctuation">,</span> <span class="Identifier">ri</span><span class="Punctuation">:</span> <span class="Identifier">BinaryTree</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span> <span class="Comment"># left and right subtrees; may be nil</span>
- <span class="Identifier">data</span><span class="Punctuation">:</span> <span class="Identifier">T</span> <span class="Comment"># the data stored in a node</span>
- <span class="Keyword">proc</span> <span class="Identifier">newNode</span><span class="Operator">*</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span><span class="Punctuation">(</span><span class="Identifier">data</span><span class="Punctuation">:</span> <span class="Identifier">T</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">BinaryTree</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span> <span class="Operator">=</span>
- <span class="Comment"># constructor for a node</span>
- <span class="Identifier">new</span><span class="Punctuation">(</span><span class="Identifier">result</span><span class="Punctuation">)</span>
- <span class="Identifier">result</span><span class="Operator">.</span><span class="Identifier">data</span> <span class="Operator">=</span> <span class="Identifier">data</span>
- <span class="Keyword">proc</span> <span class="Identifier">add</span><span class="Operator">*</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span><span class="Punctuation">(</span><span class="Identifier">root</span><span class="Punctuation">:</span> <span class="Keyword">var</span> <span class="Identifier">BinaryTree</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span><span class="Punctuation">,</span> <span class="Identifier">n</span><span class="Punctuation">:</span> <span class="Identifier">BinaryTree</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span><span class="Punctuation">)</span> <span class="Operator">=</span>
- <span class="Comment"># insert a node into the tree</span>
- <span class="Keyword">if</span> <span class="Identifier">root</span> <span class="Operator">==</span> <span class="Keyword">nil</span><span class="Punctuation">:</span>
- <span class="Identifier">root</span> <span class="Operator">=</span> <span class="Identifier">n</span>
- <span class="Keyword">else</span><span class="Punctuation">:</span>
- <span class="Keyword">var</span> <span class="Identifier">it</span> <span class="Operator">=</span> <span class="Identifier">root</span>
- <span class="Keyword">while</span> <span class="Identifier">it</span> <span class="Operator">!=</span> <span class="Keyword">nil</span><span class="Punctuation">:</span>
- <span class="Comment"># compare the data items; uses the generic `cmp` proc</span>
- <span class="Comment"># that works for any type that has a `==` and `<` operator</span>
- <span class="Keyword">var</span> <span class="Identifier">c</span> <span class="Operator">=</span> <span class="Identifier">cmp</span><span class="Punctuation">(</span><span class="Identifier">it</span><span class="Operator">.</span><span class="Identifier">data</span><span class="Punctuation">,</span> <span class="Identifier">n</span><span class="Operator">.</span><span class="Identifier">data</span><span class="Punctuation">)</span>
- <span class="Keyword">if</span> <span class="Identifier">c</span> <span class="Operator"><</span> <span class="DecNumber">0</span><span class="Punctuation">:</span>
- <span class="Keyword">if</span> <span class="Identifier">it</span><span class="Operator">.</span><span class="Identifier">le</span> <span class="Operator">==</span> <span class="Keyword">nil</span><span class="Punctuation">:</span>
- <span class="Identifier">it</span><span class="Operator">.</span><span class="Identifier">le</span> <span class="Operator">=</span> <span class="Identifier">n</span>
- <span class="Keyword">return</span>
- <span class="Identifier">it</span> <span class="Operator">=</span> <span class="Identifier">it</span><span class="Operator">.</span><span class="Identifier">le</span>
- <span class="Keyword">else</span><span class="Punctuation">:</span>
- <span class="Keyword">if</span> <span class="Identifier">it</span><span class="Operator">.</span><span class="Identifier">ri</span> <span class="Operator">==</span> <span class="Keyword">nil</span><span class="Punctuation">:</span>
- <span class="Identifier">it</span><span class="Operator">.</span><span class="Identifier">ri</span> <span class="Operator">=</span> <span class="Identifier">n</span>
- <span class="Keyword">return</span>
- <span class="Identifier">it</span> <span class="Operator">=</span> <span class="Identifier">it</span><span class="Operator">.</span><span class="Identifier">ri</span>
- <span class="Keyword">proc</span> <span class="Identifier">add</span><span class="Operator">*</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span><span class="Punctuation">(</span><span class="Identifier">root</span><span class="Punctuation">:</span> <span class="Keyword">var</span> <span class="Identifier">BinaryTree</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span><span class="Punctuation">,</span> <span class="Identifier">data</span><span class="Punctuation">:</span> <span class="Identifier">T</span><span class="Punctuation">)</span> <span class="Operator">=</span>
- <span class="Comment"># convenience proc:</span>
- <span class="Identifier">add</span><span class="Punctuation">(</span><span class="Identifier">root</span><span class="Punctuation">,</span> <span class="Identifier">newNode</span><span class="Punctuation">(</span><span class="Identifier">data</span><span class="Punctuation">)</span><span class="Punctuation">)</span>
- <span class="Keyword">iterator</span> <span class="Identifier">preorder</span><span class="Operator">*</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span><span class="Punctuation">(</span><span class="Identifier">root</span><span class="Punctuation">:</span> <span class="Identifier">BinaryTree</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">T</span> <span class="Operator">=</span>
- <span class="Comment"># Preorder traversal of a binary tree.</span>
- <span class="Comment"># This uses an explicit stack (which is more efficient than</span>
- <span class="Comment"># a recursive iterator factory).</span>
- <span class="Keyword">var</span> <span class="Identifier">stack</span><span class="Punctuation">:</span> <span class="Identifier">seq</span><span class="Punctuation">[</span><span class="Identifier">BinaryTree</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span><span class="Punctuation">]</span> <span class="Operator">=</span> <span class="Operator">@</span><span class="Punctuation">[</span><span class="Identifier">root</span><span class="Punctuation">]</span>
- <span class="Keyword">while</span> <span class="Identifier">stack</span><span class="Operator">.</span><span class="Identifier">len</span> <span class="Operator">></span> <span class="DecNumber">0</span><span class="Punctuation">:</span>
- <span class="Keyword">var</span> <span class="Identifier">n</span> <span class="Operator">=</span> <span class="Identifier">stack</span><span class="Operator">.</span><span class="Identifier">pop</span><span class="Punctuation">(</span><span class="Punctuation">)</span>
- <span class="Keyword">while</span> <span class="Identifier">n</span> <span class="Operator">!=</span> <span class="Keyword">nil</span><span class="Punctuation">:</span>
- <span class="Keyword">yield</span> <span class="Identifier">n</span><span class="Operator">.</span><span class="Identifier">data</span>
- <span class="Identifier">add</span><span class="Punctuation">(</span><span class="Identifier">stack</span><span class="Punctuation">,</span> <span class="Identifier">n</span><span class="Operator">.</span><span class="Identifier">ri</span><span class="Punctuation">)</span> <span class="Comment"># push right subtree onto the stack</span>
- <span class="Identifier">n</span> <span class="Operator">=</span> <span class="Identifier">n</span><span class="Operator">.</span><span class="Identifier">le</span> <span class="Comment"># and follow the left pointer</span>
- <span class="Keyword">var</span>
- <span class="Identifier">root</span><span class="Punctuation">:</span> <span class="Identifier">BinaryTree</span><span class="Punctuation">[</span><span class="Identifier">string</span><span class="Punctuation">]</span> <span class="Comment"># instantiate a BinaryTree with `string`</span>
- <span class="Identifier">add</span><span class="Punctuation">(</span><span class="Identifier">root</span><span class="Punctuation">,</span> <span class="Identifier">newNode</span><span class="Punctuation">(</span><span class="StringLit">"hello"</span><span class="Punctuation">)</span><span class="Punctuation">)</span> <span class="Comment"># instantiates `newNode` and `add`</span>
- <span class="Identifier">add</span><span class="Punctuation">(</span><span class="Identifier">root</span><span class="Punctuation">,</span> <span class="StringLit">"world"</span><span class="Punctuation">)</span> <span class="Comment"># instantiates the second `add` proc</span>
- <span class="Keyword">for</span> <span class="Identifier">str</span> <span class="Keyword">in</span> <span class="Identifier">preorder</span><span class="Punctuation">(</span><span class="Identifier">root</span><span class="Punctuation">)</span><span class="Punctuation">:</span>
- <span class="Identifier">stdout</span><span class="Operator">.</span><span class="Identifier">writeLine</span><span class="Punctuation">(</span><span class="Identifier">str</span><span class="Punctuation">)</span></pre></p>
- <p>The example shows a generic binary tree. Depending on context, the brackets are used either to introduce type parameters or to instantiate a generic proc, iterator or type. As the example shows, generics work with overloading: the best match of <tt class="docutils literal"><span class="pre"><span class="Identifier">add</span></span></tt> is used. The built-in <tt class="docutils literal"><span class="pre"><span class="Identifier">add</span></span></tt> procedure for sequences is not hidden and is used in the <tt class="docutils literal"><span class="pre"><span class="Identifier">preorder</span></span></tt> iterator.</p>
- <p>There is a special <tt class="docutils literal"><span class="pre"><span class="Punctuation">[</span><span class="Punctuation">:</span><span class="Identifier">T</span><span class="Punctuation">]</span></span></tt> syntax when using generics with the method call syntax:</p>
- <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">foo</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span><span class="Punctuation">(</span><span class="Identifier">i</span><span class="Punctuation">:</span> <span class="Identifier">T</span><span class="Punctuation">)</span> <span class="Operator">=</span>
- <span class="Keyword">discard</span>
- <span class="Keyword">var</span> <span class="Identifier">i</span><span class="Punctuation">:</span> <span class="Identifier">int</span>
- <span class="Comment"># i.foo[int]() # Error: expression 'foo(i)' has no type (or is ambiguous)</span>
- <span class="Identifier">i</span><span class="Operator">.</span><span class="Identifier">foo</span><span class="Punctuation">[</span><span class="Punctuation">:</span><span class="Identifier">int</span><span class="Punctuation">]</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Comment"># Success</span></pre></p>
- <h1><a class="toc-backref" id="templates" href="#templates">Templates</a></h1><p>Templates are a simple substitution mechanism that operates on Nim's abstract syntax trees. Templates are processed in the semantic pass of the compiler. They integrate well with the rest of the language and share none of C's preprocessor macros flaws.</p>
- <p>To <em>invoke</em> a template, call it like a procedure.</p>
- <p>Example:</p>
- <p><pre class="listing"><span class="Keyword">template</span> <span class="Punctuation">`</span><span class="Operator">!=</span><span class="Punctuation">`</span> <span class="Punctuation">(</span><span class="Identifier">a</span><span class="Punctuation">,</span> <span class="Identifier">b</span><span class="Punctuation">:</span> <span class="Identifier">untyped</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">untyped</span> <span class="Operator">=</span>
- <span class="Comment"># this definition exists in the System module</span>
- <span class="Keyword">not</span> <span class="Punctuation">(</span><span class="Identifier">a</span> <span class="Operator">==</span> <span class="Identifier">b</span><span class="Punctuation">)</span>
- <span class="Identifier">assert</span><span class="Punctuation">(</span><span class="DecNumber">5</span> <span class="Operator">!=</span> <span class="DecNumber">6</span><span class="Punctuation">)</span> <span class="Comment"># the compiler rewrites that to: assert(not (5 == 6))</span></pre></p>
- <p>The <tt class="docutils literal"><span class="pre"><span class="Operator">!=</span></span></tt>, <tt class="docutils literal"><span class="pre"><span class="Operator">></span></span></tt>, <tt class="docutils literal"><span class="pre"><span class="Operator">>=</span></span></tt>, <tt class="docutils literal"><span class="pre"><span class="Keyword">in</span></span></tt>, <tt class="docutils literal"><span class="pre"><span class="Keyword">notin</span></span></tt>, <tt class="docutils literal"><span class="pre"><span class="Keyword">isnot</span></span></tt> operators are in fact templates: this has the benefit that if you overload the <tt class="docutils literal"><span class="pre"><span class="Operator">==</span></span></tt> operator, the <tt class="docutils literal"><span class="pre"><span class="Operator">!=</span></span></tt> operator is available automatically and does the right thing. (Except for IEEE floating point numbers - NaN breaks basic boolean logic.)</p>
- <p><tt class="docutils literal"><span class="pre"><span class="Identifier">a</span> <span class="Operator">></span> <span class="Identifier">b</span></span></tt> is transformed into <tt class="docutils literal"><span class="pre"><span class="Identifier">b</span> <span class="Operator"><</span> <span class="Identifier">a</span></span></tt>. <tt class="docutils literal"><span class="pre"><span class="Identifier">a</span> <span class="Keyword">in</span> <span class="Identifier">b</span></span></tt> is transformed into <tt class="docutils literal"><span class="pre"><span class="Identifier">contains</span><span class="Punctuation">(</span><span class="Identifier">b</span><span class="Punctuation">,</span> <span class="Identifier">a</span><span class="Punctuation">)</span></span></tt>. <tt class="docutils literal"><span class="pre"><span class="Keyword">notin</span></span></tt> and <tt class="docutils literal"><span class="pre"><span class="Keyword">isnot</span></span></tt> have the obvious meanings.</p>
- <p>Templates are especially useful for lazy evaluation purposes. Consider a simple proc for logging:</p>
- <p><pre class="listing"><span class="Keyword">const</span>
- <span class="Identifier">debug</span> <span class="Operator">=</span> <span class="Identifier">true</span>
- <span class="Keyword">proc</span> <span class="Identifier">log</span><span class="Punctuation">(</span><span class="Identifier">msg</span><span class="Punctuation">:</span> <span class="Identifier">string</span><span class="Punctuation">)</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">inline</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Operator">=</span>
- <span class="Keyword">if</span> <span class="Identifier">debug</span><span class="Punctuation">:</span> <span class="Identifier">stdout</span><span class="Operator">.</span><span class="Identifier">writeLine</span><span class="Punctuation">(</span><span class="Identifier">msg</span><span class="Punctuation">)</span>
- <span class="Keyword">var</span>
- <span class="Identifier">x</span> <span class="Operator">=</span> <span class="DecNumber">4</span>
- <span class="Identifier">log</span><span class="Punctuation">(</span><span class="StringLit">"x has the value: "</span> <span class="Operator">&</span> <span class="Operator">$</span><span class="Identifier">x</span><span class="Punctuation">)</span></pre></p>
- <p>This code has a shortcoming: if <tt class="docutils literal"><span class="pre"><span class="Identifier">debug</span></span></tt> is set to false someday, the quite expensive <tt class="docutils literal"><span class="pre"><span class="Operator">$</span></span></tt> and <tt class="docutils literal"><span class="pre"><span class="Operator">&</span></span></tt> operations are still performed! (The argument evaluation for procedures is <em>eager</em>).</p>
- <p>Turning the <tt class="docutils literal"><span class="pre"><span class="Identifier">log</span></span></tt> proc into a template solves this problem:</p>
- <p><pre class="listing"><span class="Keyword">const</span>
- <span class="Identifier">debug</span> <span class="Operator">=</span> <span class="Identifier">true</span>
- <span class="Keyword">template</span> <span class="Identifier">log</span><span class="Punctuation">(</span><span class="Identifier">msg</span><span class="Punctuation">:</span> <span class="Identifier">string</span><span class="Punctuation">)</span> <span class="Operator">=</span>
- <span class="Keyword">if</span> <span class="Identifier">debug</span><span class="Punctuation">:</span> <span class="Identifier">stdout</span><span class="Operator">.</span><span class="Identifier">writeLine</span><span class="Punctuation">(</span><span class="Identifier">msg</span><span class="Punctuation">)</span>
- <span class="Keyword">var</span>
- <span class="Identifier">x</span> <span class="Operator">=</span> <span class="DecNumber">4</span>
- <span class="Identifier">log</span><span class="Punctuation">(</span><span class="StringLit">"x has the value: "</span> <span class="Operator">&</span> <span class="Operator">$</span><span class="Identifier">x</span><span class="Punctuation">)</span></pre></p>
- <p>The parameters' types can be ordinary types or the meta types <tt class="docutils literal"><span class="pre"><span class="Identifier">untyped</span></span></tt>, <tt class="docutils literal"><span class="pre"><span class="Identifier">typed</span></span></tt>, or <tt class="docutils literal"><span class="pre"><span class="Keyword">type</span></span></tt>. <tt class="docutils literal"><span class="pre"><span class="Keyword">type</span></span></tt> suggests that only a type symbol may be given as an argument, and <tt class="docutils literal"><span class="pre"><span class="Identifier">untyped</span></span></tt> means symbol lookups and type resolution is not performed before the expression is passed to the template.</p>
- <p>If the template has no explicit return type, <tt class="docutils literal"><span class="pre"><span class="Identifier">void</span></span></tt> is used for consistency with procs and methods.</p>
- <p>To pass a block of statements to a template, use <tt class="docutils literal"><span class="pre"><span class="Identifier">untyped</span></span></tt> for the last parameter:</p>
- <p><pre class="listing"><span class="Keyword">template</span> <span class="Identifier">withFile</span><span class="Punctuation">(</span><span class="Identifier">f</span><span class="Punctuation">:</span> <span class="Identifier">untyped</span><span class="Punctuation">,</span> <span class="Identifier">filename</span><span class="Punctuation">:</span> <span class="Identifier">string</span><span class="Punctuation">,</span> <span class="Identifier">mode</span><span class="Punctuation">:</span> <span class="Identifier">FileMode</span><span class="Punctuation">,</span>
- <span class="Identifier">body</span><span class="Punctuation">:</span> <span class="Identifier">untyped</span><span class="Punctuation">)</span> <span class="Operator">=</span>
- <span class="Keyword">let</span> <span class="Identifier">fn</span> <span class="Operator">=</span> <span class="Identifier">filename</span>
- <span class="Keyword">var</span> <span class="Identifier">f</span><span class="Punctuation">:</span> <span class="Identifier">File</span>
- <span class="Keyword">if</span> <span class="Identifier">open</span><span class="Punctuation">(</span><span class="Identifier">f</span><span class="Punctuation">,</span> <span class="Identifier">fn</span><span class="Punctuation">,</span> <span class="Identifier">mode</span><span class="Punctuation">)</span><span class="Punctuation">:</span>
- <span class="Keyword">try</span><span class="Punctuation">:</span>
- <span class="Identifier">body</span>
- <span class="Keyword">finally</span><span class="Punctuation">:</span>
- <span class="Identifier">close</span><span class="Punctuation">(</span><span class="Identifier">f</span><span class="Punctuation">)</span>
- <span class="Keyword">else</span><span class="Punctuation">:</span>
- <span class="Identifier">quit</span><span class="Punctuation">(</span><span class="StringLit">"cannot open: "</span> <span class="Operator">&</span> <span class="Identifier">fn</span><span class="Punctuation">)</span>
- <span class="Identifier">withFile</span><span class="Punctuation">(</span><span class="Identifier">txt</span><span class="Punctuation">,</span> <span class="StringLit">"ttempl3.txt"</span><span class="Punctuation">,</span> <span class="Identifier">fmWrite</span><span class="Punctuation">)</span><span class="Punctuation">:</span>
- <span class="Identifier">txt</span><span class="Operator">.</span><span class="Identifier">writeLine</span><span class="Punctuation">(</span><span class="StringLit">"line 1"</span><span class="Punctuation">)</span>
- <span class="Identifier">txt</span><span class="Operator">.</span><span class="Identifier">writeLine</span><span class="Punctuation">(</span><span class="StringLit">"line 2"</span><span class="Punctuation">)</span></pre></p>
- <p>In the example the two <tt class="docutils literal"><span class="pre"><span class="Identifier">writeLine</span></span></tt> statements are bound to the <tt class="docutils literal"><span class="pre"><span class="Identifier">body</span></span></tt> parameter. The <tt class="docutils literal"><span class="pre"><span class="Identifier">withFile</span></span></tt> template contains boilerplate code and helps to avoid a common bug: to forget to close the file. Note how the <tt class="docutils literal"><span class="pre"><span class="Keyword">let</span> <span class="Identifier">fn</span> <span class="Operator">=</span> <span class="Identifier">filename</span></span></tt> statement ensures that <tt class="docutils literal"><span class="pre"><span class="Identifier">filename</span></span></tt> is evaluated only once.</p>
- <h2><a class="toc-backref" id="templates-examplecolon-lifting-procs" href="#templates-examplecolon-lifting-procs">Example: Lifting Procs</a></h2><p><pre class="listing"><span class="Keyword">import</span> <span class="Identifier">std</span><span class="Operator">/</span><span class="Identifier">math</span>
- <span class="Keyword">template</span> <span class="Identifier">liftScalarProc</span><span class="Punctuation">(</span><span class="Identifier">fname</span><span class="Punctuation">)</span> <span class="Operator">=</span>
- <span class="Comment">## Lift a proc taking one scalar parameter and returning a</span>
- <span class="Comment">## scalar value (eg `proc sssss[T](x: T): float`),</span>
- <span class="Comment">## to provide templated procs that can handle a single</span>
- <span class="Comment">## parameter of seq[T] or nested seq[seq[]] or the same type</span>
- <span class="Comment">##</span>
- <span class="Comment">## ```Nim</span>
- <span class="Comment">## liftScalarProc(abs)</span>
- <span class="Comment">## # now abs(@[@[1,-2], @[-2,-3]]) == @[@[1,2], @[2,3]]</span>
- <span class="Comment">## ```</span>
- <span class="Keyword">proc</span> <span class="Identifier">fname</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span><span class="Punctuation">(</span><span class="Identifier">x</span><span class="Punctuation">:</span> <span class="Identifier">openarray</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">auto</span> <span class="Operator">=</span>
- <span class="Keyword">var</span> <span class="Identifier">temp</span><span class="Punctuation">:</span> <span class="Identifier">T</span>
- <span class="Keyword">type</span> <span class="Identifier">outType</span> <span class="Operator">=</span> <span class="Identifier">typeof</span><span class="Punctuation">(</span><span class="Identifier">fname</span><span class="Punctuation">(</span><span class="Identifier">temp</span><span class="Punctuation">)</span><span class="Punctuation">)</span>
- <span class="Identifier">result</span> <span class="Operator">=</span> <span class="Identifier">newSeq</span><span class="Punctuation">[</span><span class="Identifier">outType</span><span class="Punctuation">]</span><span class="Punctuation">(</span><span class="Identifier">x</span><span class="Operator">.</span><span class="Identifier">len</span><span class="Punctuation">)</span>
- <span class="Keyword">for</span> <span class="Identifier">i</span> <span class="Keyword">in</span> <span class="FloatNumber">0.</span><span class="Operator">.<</span><span class="Identifier">x</span><span class="Operator">.</span><span class="Identifier">len</span><span class="Punctuation">:</span>
- <span class="Identifier">result</span><span class="Punctuation">[</span><span class="Identifier">i</span><span class="Punctuation">]</span> <span class="Operator">=</span> <span class="Identifier">fname</span><span class="Punctuation">(</span><span class="Identifier">x</span><span class="Punctuation">[</span><span class="Identifier">i</span><span class="Punctuation">]</span><span class="Punctuation">)</span>
- <span class="Identifier">liftScalarProc</span><span class="Punctuation">(</span><span class="Identifier">sqrt</span><span class="Punctuation">)</span> <span class="Comment"># make sqrt() work for sequences</span>
- <span class="Identifier">echo</span> <span class="Identifier">sqrt</span><span class="Punctuation">(</span><span class="Operator">@</span><span class="Punctuation">[</span><span class="FloatNumber">4.0</span><span class="Punctuation">,</span> <span class="FloatNumber">16.0</span><span class="Punctuation">,</span> <span class="FloatNumber">25.0</span><span class="Punctuation">,</span> <span class="FloatNumber">36.0</span><span class="Punctuation">]</span><span class="Punctuation">)</span> <span class="Comment"># => @[2.0, 4.0, 5.0, 6.0]</span></pre></p>
- <h1><a class="toc-backref" id="compilation-to-javascript" href="#compilation-to-javascript">Compilation to JavaScript</a></h1><p>Nim code can be compiled to JavaScript. However in order to write JavaScript-compatible code you should remember the following:</p>
- <ul class="simple"><li><tt class="docutils literal"><span class="pre"><span class="Keyword">addr</span></span></tt> and <tt class="docutils literal"><span class="pre"><span class="Keyword">ptr</span></span></tt> have slightly different semantic meaning in JavaScript. It is recommended to avoid those if you're not sure how they are translated to JavaScript.</li>
- <li><tt class="docutils literal"><span class="pre"><span class="Keyword">cast</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span><span class="Punctuation">(</span><span class="Identifier">x</span><span class="Punctuation">)</span></span></tt> in JavaScript is translated to <tt class="docutils literal"><span class="pre"><span class="Punctuation">(</span><span class="Identifier">x</span><span class="Punctuation">)</span></span></tt>, except for casting between signed/unsigned ints, in which case it behaves as static cast in C language.</li>
- <li><tt class="docutils literal"><span class="pre"><span class="Identifier">cstring</span></span></tt> in JavaScript means JavaScript string. It is a good practice to use <tt class="docutils literal"><span class="pre"><span class="Identifier">cstring</span></span></tt> only when it is semantically appropriate. E.g. don't use <tt class="docutils literal"><span class="pre"><span class="Identifier">cstring</span></span></tt> as a binary data buffer.</li>
- </ul>
- <h1><a class="toc-backref" id="part-3" href="#part-3">Part 3</a></h1><p>The next part is entirely about metaprogramming via macros: <a class="reference external" href="tut3.html">Part III</a>. </p>
- </p>
-
- </div>
- </div>
- <div class="twelve-columns footer">
- <span class="nim-sprite"></span>
- <br>
- <small style="color: var(--hint);">Made with Nim. Generated: 2025-01-09 11:59:49 UTC</small>
- </div>
- </div>
- </div>
- <script defer data-domain="nim-lang.org" src="https://plausible.io/js/plausible.js"></script>
-
- </body>
- </html>
|