├── .gitignore ├── LICENSE ├── README.md ├── dynamic_approximating_dynamic_types.nim ├── macros_register_hooks.nim ├── multiline_echo.nim └── undefining_variable.nim /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | CC0 1.0 Universal 3 | 4 | Statement of Purpose 5 | 6 | The laws of most jurisdictions throughout the world automatically confer 7 | exclusive Copyright and Related Rights (defined below) upon the creator and 8 | subsequent owner(s) (each and all, an "owner") of an original work of 9 | authorship and/or a database (each, a "Work"). 10 | 11 | Certain owners wish to permanently relinquish those rights to a Work for the 12 | purpose of contributing to a commons of creative, cultural and scientific 13 | works ("Commons") that the public can reliably and without fear of later 14 | claims of infringement build upon, modify, incorporate in other works, reuse 15 | and redistribute as freely as possible in any form whatsoever and for any 16 | purposes, including without limitation commercial purposes. These owners may 17 | contribute to the Commons to promote the ideal of a free culture and the 18 | further production of creative, cultural and scientific works, or to gain 19 | reputation or greater distribution for their Work in part through the use and 20 | efforts of others. 21 | 22 | For these and/or other purposes and motivations, and without any expectation 23 | of additional consideration or compensation, the person associating CC0 with a 24 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 25 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 26 | and publicly distribute the Work under its terms, with knowledge of his or her 27 | Copyright and Related Rights in the Work and the meaning and intended legal 28 | effect of CC0 on those rights. 29 | 30 | 1. Copyright and Related Rights. A Work made available under CC0 may be 31 | protected by copyright and related or neighboring rights ("Copyright and 32 | Related Rights"). Copyright and Related Rights include, but are not limited 33 | to, the following: 34 | 35 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 36 | and translate a Work; 37 | 38 | ii. moral rights retained by the original author(s) and/or performer(s); 39 | 40 | iii. publicity and privacy rights pertaining to a person's image or likeness 41 | depicted in a Work; 42 | 43 | iv. rights protecting against unfair competition in regards to a Work, 44 | subject to the limitations in paragraph 4(a), below; 45 | 46 | v. rights protecting the extraction, dissemination, use and reuse of data in 47 | a Work; 48 | 49 | vi. database rights (such as those arising under Directive 96/9/EC of the 50 | European Parliament and of the Council of 11 March 1996 on the legal 51 | protection of databases, and under any national implementation thereof, 52 | including any amended or successor version of such directive); and 53 | 54 | vii. other similar, equivalent or corresponding rights throughout the world 55 | based on applicable law or treaty, and any national implementations thereof. 56 | 57 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 58 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 59 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 60 | and Related Rights and associated claims and causes of action, whether now 61 | known or unknown (including existing as well as future claims and causes of 62 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 63 | duration provided by applicable law or treaty (including future time 64 | extensions), (iii) in any current or future medium and for any number of 65 | copies, and (iv) for any purpose whatsoever, including without limitation 66 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 67 | the Waiver for the benefit of each member of the public at large and to the 68 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 69 | shall not be subject to revocation, rescission, cancellation, termination, or 70 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 71 | by the public as contemplated by Affirmer's express Statement of Purpose. 72 | 73 | 3. Public License Fallback. Should any part of the Waiver for any reason be 74 | judged legally invalid or ineffective under applicable law, then the Waiver 75 | shall be preserved to the maximum extent permitted taking into account 76 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 77 | is so judged Affirmer hereby grants to each affected person a royalty-free, 78 | non transferable, non sublicensable, non exclusive, irrevocable and 79 | unconditional license to exercise Affirmer's Copyright and Related Rights in 80 | the Work (i) in all territories worldwide, (ii) for the maximum duration 81 | provided by applicable law or treaty (including future time extensions), (iii) 82 | in any current or future medium and for any number of copies, and (iv) for any 83 | purpose whatsoever, including without limitation commercial, advertising or 84 | promotional purposes (the "License"). The License shall be deemed effective as 85 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 86 | License for any reason be judged legally invalid or ineffective under 87 | applicable law, such partial invalidity or ineffectiveness shall not 88 | invalidate the remainder of the License, and in such case Affirmer hereby 89 | affirms that he or she will not (i) exercise any of his or her remaining 90 | Copyright and Related Rights in the Work or (ii) assert any associated claims 91 | and causes of action with respect to the Work, in either case contrary to 92 | Affirmer's express Statement of Purpose. 93 | 94 | 4. Limitations and Disclaimers. 95 | 96 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 97 | surrendered, licensed or otherwise affected by this document. 98 | 99 | b. Affirmer offers the Work as-is and makes no representations or warranties 100 | of any kind concerning the Work, express, implied, statutory or otherwise, 101 | including without limitation warranties of title, merchantability, fitness 102 | for a particular purpose, non infringement, or the absence of latent or 103 | other defects, accuracy, or the present or absence of errors, whether or not 104 | discoverable, all to the greatest extent permissible under applicable law. 105 | 106 | c. Affirmer disclaims responsibility for clearing rights of other persons 107 | that may apply to the Work or any use thereof, including without limitation 108 | any person's Copyright and Related Rights in the Work. Further, Affirmer 109 | disclaims responsibility for obtaining any necessary consents, permissions 110 | or other rights required for any use of the Work. 111 | 112 | d. Affirmer understands and acknowledges that Creative Commons is not a 113 | party to this document and has no duty or obligation with respect to this 114 | CC0 or use of the Work. 115 | 116 | For more information, please see 117 | 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nim cookbook 2 | 3 | Recipes in Nim 4 | 5 | For now, the cookbook is so short so no real organization or taxonomy is needed. 6 | 7 | Compile examples with 8 | 9 | ```sh 10 | nim c -r --outdir:build/ myexample.nim 11 | ``` 12 | 13 | 14 | # License 15 | 16 | [CC Zero](https://creativecommons.org/share-your-work/public-domain/cc0/) 17 | -------------------------------------------------------------------------------- /dynamic_approximating_dynamic_types.nim: -------------------------------------------------------------------------------- 1 | # Context 2 | # https://forum.nim-lang.org/t/5000#31345 3 | # 4 | # The goal is to approximate the dynamic creation of properties 5 | # we use Nim dot operators for that and store everything in a Json object. 6 | 7 | import json 8 | 9 | {.experimental: "dotOperators".} 10 | 11 | type 12 | Action = ref object 13 | properties: JsonNode 14 | 15 | template `.`(action: Action, field: untyped): untyped = 16 | action.properties[astToStr(field)] 17 | 18 | template `.=`(action: Action, field, value: untyped): untyped = 19 | action.properties[astToStr(field)] = %value 20 | 21 | 22 | # Our main object, the fields are dynamic 23 | 24 | var a = Action( 25 | properties: %*{ 26 | "layer": 0, 27 | "add": true, 28 | "vis": false, 29 | "new_name": "fancy_name" 30 | } 31 | ) 32 | 33 | # And usage, those are not real fields but there is no difference in syntax 34 | 35 | echo a.new_name # "fancy_name" 36 | 37 | a.algo = 10 38 | echo a.algo # 10 39 | -------------------------------------------------------------------------------- /macros_register_hooks.nim: -------------------------------------------------------------------------------- 1 | # Context 2 | # https://forum.nim-lang.org/t/5450 3 | # 4 | # A macro that inserts code somewhere else 5 | # 6 | # ``` 7 | # registerHook post_foo: 8 | # echo “foo done. x=“, x 9 | # 10 | # ... 11 | # 12 | # proc foo = 13 | # let x = 10 14 | # runHooks post_foo 15 | # 16 | 17 | # Solution 1 - Using {.dirty.} templates 18 | # -------------------------------------------------------------------------------------------------------- 19 | 20 | block: 21 | template post_foo(): untyped {.dirty.} = 22 | echo "foo done. x=", x 23 | 24 | proc foo = 25 | let x = 10 26 | post_foo() 27 | 28 | # Solution 2 - Using a compile-time table 29 | # -------------------------------------------------------------------------------------------------------- 30 | 31 | import tables, macros 32 | block: # 33 | var hooks {.compileTime.}: Table[string, NimNode] # Can use custom hashing for NimNode instead of strings 34 | 35 | macro registerHook(name: untyped{ident}, body: untyped): untyped = 36 | result = newStmtList() 37 | result.add newProc( 38 | name = name, 39 | body = body, 40 | # need a dirty template to capture x 41 | procType = nnkTemplateDef, 42 | pragmas = nnkPragma.newTree(ident"dirty") 43 | ) 44 | 45 | hooks[$name] = name 46 | 47 | macro runHooks(hook: untyped): untyped = 48 | result = newCall(hooks[$hook]) 49 | 50 | registerHook post_foo: 51 | # need a dirty template to capture x 52 | echo "foo done. x=", x 53 | 54 | proc foo = 55 | let x = 10 56 | runHooks post_foo 57 | 58 | proc main() = 59 | foo() 60 | echo "The end." 61 | 62 | main() 63 | 64 | # Solution 3 - Using macros as pragmas 65 | # -------------------------------------------------------------------------------------------------------- 66 | 67 | import macros 68 | block: 69 | macro registerHook(name: untyped{ident}, body: untyped): untyped = 70 | result = newStmtList() 71 | result.add newProc( 72 | name = name, 73 | body = body, 74 | # need a dirty template to capture x 75 | procType = nnkTemplateDef, 76 | pragmas = nnkPragma.newTree(ident"dirty") 77 | ) 78 | 79 | macro runHook(pragma: untyped, moddedProc: untyped): untyped = 80 | result = moddedProc 81 | 82 | result[6].expectKind(nnkStmtList) 83 | result[6].add newCall(pragma) 84 | 85 | registerHook post_foo: 86 | # need a dirty template to capture x 87 | echo "foo done. x=", x 88 | 89 | proc foo {.runHook: post_foo.}= 90 | let x = 10 91 | 92 | proc main() = 93 | foo() 94 | echo "The end." 95 | 96 | main() 97 | -------------------------------------------------------------------------------- /multiline_echo.nim: -------------------------------------------------------------------------------- 1 | import macros 2 | 3 | macro echoAll(body: untyped): untyped = 4 | result = newStmtList() 5 | 6 | for s in body: 7 | result.add newCall(bindSym"echo", s) 8 | 9 | 10 | echoAll: 11 | "Hello" 12 | "World" 13 | 1234 14 | -------------------------------------------------------------------------------- /undefining_variable.nim: -------------------------------------------------------------------------------- 1 | # Context 2 | # 3 | # Discussion with PMunch on IRC to disallow the use of some variable 4 | # in a code block 5 | 6 | template undef(symbol: untyped{nkIdent}, body: untyped{nkStmtList}): untyped = 7 | block: 8 | template `symbol`(): untyped = {.error: "Cannot use `" & astToStr(`symbol`) & "` in this undef context".} 9 | body 10 | 11 | var x = 100 12 | echo x 13 | 14 | undef(x): 15 | echo x 16 | --------------------------------------------------------------------------------