Document your code
Every project on GitHub comes with a version-controlled wiki to give your documentation the high level of care it deserves. It’s easy to create well-maintained, Markdown or rich text documentation alongside your code.
Sign up for free See pricing for teams and enterprisesNim for Python Programmers
Table Of Contents
DISCLAIMER!
Unofficial, work in progress! This is still a stub. Please help extending it. There may be inaccuracies in this guide. This is a guide for people with experience in Python or a similar language. The guide assumes some intermediate knowledge.
The general tutorials can be found here:
http://nim-lang.org/docs/tut1.html
http://nim-lang.org/docs/tut2.html
The manual provides an overview of the language: http://nim-lang.org/docs/manual.html
Comparison
| Feature |
|
|
|---|---|---|
| Execution model | Virtual Machine, JIT (Interpreter) | Machine code via C/C++ (Compiler) |
| Written using | C | Nim |
| License | Python Software Foundation License | MIT |
| Version (Mayor) | 3.x |
1.x |
| Meta-programming |
|
|
| Memory Management | Garbage collector | Garbage collector or manual |
| Typing | Dynamic | Static |
| Dependent types |
|
|
| Generics | Duck typing | |
| int8/16/32/64 types | ||
| float32/float64 types | ||
| Char types | ||
| Subrange types | ||
| Enum types | ||
| Bigints (arbitrary size) |
|
|
| Biggest Integer Std Lib | Unknown? |
18_446_744_073_709_551_615, uint64() type |
| Arrays | ||
| Type inference | Duck typing | |
| Closures | ||
| Operator Overloading |
|
|
| Custom Operators | ||
| Object-Oriented | ||
| Methods | ||
| Exceptions | ||
| Anonymous Functions |
|
|
| List Comprehensions | ||
| Dict Comprehensions | ||
| Set Comprehensions | ||
| Custom Object Comprehensions | ||
| Immutability | Limited (frozenset, tuple, etc) | |
| Function Arguments Immutability | Mutable | Immutable |
| Formatted String Literals |
|
|
| FFI |
|
|
| Async | ||
| Threads |
|
|
| Regex |
|
|
| Self-Documentation comments |
|
|
| Package Publishing |
twine
|
nimble
|
| Package Manager |
pip
|
nimble
|
| Code AutoFormatter |
black via PIP |
nimpretty built-in |
| File extensions | .py, .pyi, .pyd, .pyo, .pyw, .pyz, .pyx | .nim, .nims |
| Temporary Intermediate Representation format | .pyc | C |
| Uses SheBang on files | ||
| Indentation | Tabs and Spaces | Spaces |
Variables
Creating a new variable uses var or let or const.
Nim has immutability and compile-time function execution.
You can assign functions to variables.
| Declaration | Compile-Time | Run-Time | Immutable | Requires Assignment |
|---|---|---|---|---|
var |
||||
let |
||||
const |
If you are just starting from scratch, you can use var while learning, it will not produce an error for doing so, until you learn more.
Imports
| Import |
|
|
|---|---|---|
| Only 1 symbol, use unqualified | from math import sin |
from math import sin |
| All symbols, use unqualified | from math import * |
import math (recommended) |
| All symbols, use fully qualified | import math (recommended) |
from math import nil |
| All symbols except 1, use unqualified | import math except sin |
In Nim, import math imports all the symbols from the math module (sin(), cos(), etc) so that they can be used unqualified. The Python equivalent is from math import *.
If you prefer not to import all the symbols, and instead to use qualified names, the Nim code is from math import nil. Then you can call math.sin() etc. The Python equivalent is import math.
The reasons that it is generally safe to import all names in Nim are that the compiler will not actually include any unused functions (so there's no overhead), and because Nim is statically typed it can usually distinguish between two imported functions with the same names based on the types of the arguments they are called with. And in the rare cases where the types are the same, you can still fully qualify the name to disambiguate.
Nim can use the imports on the same line. From Python to Nim as minimum as possible example:
import foo
import bar
import baz Python
Nim
import foo, bar, bazIf your line gets too long, imports can also be an indented block:
import
foo, bar, baz, more, imports,
here, we, split, multiple, lines
If you like 1 import per line, because of Git diffs, imports can also be 1 per line:
import
foo,
bar,
baz
If you are just starting from scratch, you can use imports like Python while learning, it will not produce an error for doing so, until you learn more.
For better understanding, is recommended to read: https://narimiran.github.io/2019/07/01/nim-import.html
Arrays
Arrays are fixed size, start at index 0 and can contain elements of the same type.
When passing an array to a function in Nim, the argument is an immutable reference. Nim will include run-time checks on the bounds of the arrays.
You can use an openarray to accept an array of any size on the function arguments,
and you can use low(your_array) and high(your_array) to query the bounds of the array.
Objects
Objects in Nim behave quite differently from classes in Python.
Objects support inheritance and OOP. Classes are named Types on Nim.
Functions are free floating functions, not bound to objects
(however, you can use them in a very similar way to Python),
you can call a function on objects with the Object.function().
Nim does not have an implicit self nor this.
Imagine it like functions get "glued" to the objects at compile-time, then you can use it at run-time as if it was Python class and methods.
From Python to Nim as minimum as possible example:
class Kitten(object):
""" Documentation Here """
def purr(self):
print("Purr Purr")
Kitten().purr() Python
Nim
type Kitten = object ## Documentation Here
proc purr(self: Kitten) = echo "Purr Purr"
Kitten().purr()Python-like object orientation example:
type Animal = ref object of RootObj ## Animal base object.
age: int
name: string ## Attributes of base object.
type Cat = ref object of Animal ## Cat inherited object.
playfulness: float ## Attributes of inherited object.
func increase_age(self: Cat) =
self.age.inc() # Cat object function, access and *modify* object.
var kitten = Cat(name: "Tom") # Cat object instance.
kitten.increase_age() # Cat object function used.
assert kitten.name == "Tom" # Assert on Cat object.
assert kitten.age == 1
self.__init__()
After the Cat example probably you are wondering how to do def __init__(self, arg):.
Python __init__() is Nim newObject() or initObject(), lets make an __init__() for the Cat:
type Cat = object # Cat object.
age: int
name: string # Attributes of Cat object.
func newCat(age = 2): Cat = # Cat.__init__(self, age=2)
result.age = age # self.age = age
result.name = "adopt_me" # self.name = "adopt_me"
var kitten = newCat() # Cat object instance.
assert kitten.name == "adopt_me" # Assert on Cat object.
assert kitten.age == 2Naming is a convention and best practice, when you want init for Foo just make newFoo() or initFoo().
As you may notice newCat is just a function that returns a Cat.
Read the documentation for Naming things following conventions and best practices.
Ranges
In Python, simple integer for loops use the range generator function. For the 1- and 2- argument forms of this function, nim's .. iterator works almost the same way:
for i in 0..10:
echo i # Prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
for i in 5..10:
echo i # Prints 5, 6, 7, 8, 9, 10Note that the .. operator includes the end of the range, whereas Python's range(a, b) does not include b. If you prefer this behavior, use the ..< iterator instead:
for i in 0..<10:
echo i # Prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9Python range() also has an optional third parameter,
which is the value to increment by each step, which can be positive or negative.
If you need this behavior, use the countup or
countdown iterators:
for i in countup(1, 10, 2):
echo i # Prints 1, 3, 5, 7, 9Slices
The syntax for slice ranges is different. Python a[x:y] is Nim a[x..<y].
let variable = [1, 2, 3, 4]
assert variable[0..0] == @[1]
assert variable[0..1] == @[1, 2]
assert variable[0..<2] == @[1, 2]
assert variable[0..3] == @[1, 2, 3, 4]Strings
| Lang | String | Multi-line string | Raw String | Multi-line Raw string | Quote | Always Unicode |
|---|---|---|---|---|---|---|
|
|
"foo" |
"""foo""" |
r"foo" |
r"""foo""" |
" '
|
|
|
|
"foo" |
"""foo""" |
r"foo" |
r"""foo""" |
" |
String Ops
| Ops |
|
|
|---|---|---|
| Lower | "ABCD".lower() |
"ABCD".toLowerAscii() |
| Strip | " ab ".strip() |
" ab ".strip() |
| Split | "a,b,c".split(",") |
"a,b,c".split(",") |
| Concatenation | "a" + "b" |
"a" & "b" |
| Find | "abcd".find("c") |
"abcd".find("c") |
| Starts With | "abc".startswith("ab") |
"abc".startswith("ab") |
| Ends With | "abc".endswith("ab") |
"abc".endswith("ab") |
| Split Lines | "1\n2\n3".splitlines() |
"1\n2\n3".splitlines() |
| Slicing | "abcd"[0:2] |
"abcd"[0..<2] |
| Slicing 1 char | "abcd"[2] |
"abcd"[2] |
| Reverse Slicing | "abcd"[-1] |
"abcd"[^1] |
| Normalize | unicodedata.normalize("NFC", "Foo") |
"Foo".normalize() |
| Count Lines | len("1\n2\n3".splitlines()) |
"1\n2\n3".countLines() |
| Repeat | "foo" * 9 |
"foo".repeat(9) |
| Indent | textwrap.indent("foo", " " * 9) |
"a".indent(9) |
| Unindent |
textwrap.dedent("foo") |
"foo".unindent(9) |
| Parse Bool |
bool(distutils.util.strtobool("fALse")) |
parseBool("fALse") |
| Parse Int | int("42") |
parseInt("42") |
| Parse Float | float("3.14") |
parseFloat("3.14") |
| Formatted String Literals | f"foo {1 + 2} bar {variable}" |
fmt"foo {1 + 2} bar {variable}" |
| Levenshtein distance | editDistance("Kitten", "Bitten") |
- Nim string operations requires
import strutils. - A very detailed comparison.
Standard Library Equivalents
| Use |
|
|
|---|---|---|
| Operating System | os | os |
| String operations | string | strutils |
| Date & time | datetime | times |
| Random | random | random |
| Regular expressions | re | re |
| HTTP | urllib | httpclient |
| Logging | logging | logging |
| Run external commands | subprocess | osproc |
| Path manipulation | pathlib, os.path | os |
| Mathematic | math, cmath | math |
| MIME Types | mimetypes | mimetypes |
| SQLite SQL | sqlite3 | db_sqlite |
| Postgres SQL | db_postgres | |
| Serialization | pickle | json, marshal |
| Base64 | base64 | base64 |
| Open web browser URL | webbrowser | browsers |
| Async | asyncio | asyncdispatch, asyncfile, asyncnet, asyncstreams |
| Unittests | unittests | unittest |
| Diff | difflib | diff |
| Colors | colorsys | colors |
| MD5 | hashlib.md5 | md5 |
| SHA1 | hashlib.sha1 | sha1 |
| HTTP Server | http.server | asynchttpserver |
| Lexer | shlex | lexbase |
| Multi-Threading | threading | threadpool |
| URL & URI | urllib.parse | uri |
| CSV | csv | parsecsv |
| Parse command line arguments | argparse | parseopt |
| SMTP | smtplib | smtp |
| HTTP Cookies | http.cookies | cookies |
| Statistics | statistics | stats |
| Text wrapping | textwrap | wordwrap |
| Windows Registry | winreg | registry |
| POSIX | posix | posix, posix_utils |
| SSL | ssl | openssl |
| CGI | cgi | cgi |
| Parse JSON | json | parsejson, json |
| Parse INI | configparser | parsecfg |
| Parse XML | xml | parsexml, xmltree |
| Parse HTML | html.parser | htmlparser |
| Parse SQL | parsesql | |
| Colors on the Terminal | terminal | |
| Linux Distro Detection | distros | |
| HTML Generator | htmlgen | |
| Syntax Sugar | sugar | |
| JavaScript & Frontend | dom, asyncjs, jscore, jsffi |
- Not complete just a quick overview. For more info see https://nim-lang.org/docs/lib.html
Tuples
Anonymous Tuple
(1, 2, 3) Python
Nim
(1, 2, 3)Named Tuple
- Keys named, no Tuple name. Python NamedTuple requires
import collections.
collections.namedtuple("_", "key0 key1")("foo", 42) Python
Nim
(key0: "foo", key1: 42)Named Tuple
- Keys named, Tuple named. Python NamedTuple requires
import collections.
collections.namedtuple("NameHere", "key0 key1")("foo", 42) Python
Nim
type NameHere = tuple[key0: string, key1: int]
var variable: NameHere = (key0: "foo", key1: 42)Nim Tuples are a lot like Python NamedTuple in that the tuple members have names. Nim Tuples can have mixed types.
See manual for a more in depth look at tuples.
Lists
Nim sequences are not fixed size, can grow and shrink, start at index 0 and can contain elements of the same type.
["foo", "bar", "baz"] Python
Nim
@["foo", "bar", "baz"]List Comprehensions
variable = [item for item in (-9, 1, 42, 0, -1, 9)] Python
Nim
let variable = collect(newSeq):
for item in @[-9, 1, 42, 0, -1, 9]: item- Whats
collect()?.
collect() takes as argument whatever your returning type uses as constructor.
Dict Comprehensions
variable = {key: value for key, value in enumerate((-9, 1, 42, 0, -1, 9))} Python
Nim
let variable = collect(initTable(4)):
for key, value in @[-9, 1, 42, 0, -1, 9]: {key: value}-
collect()requiresimport sugar.
Set Comprehensions
variable = {item for item in (-9, 1, 42, 0, -1, 9)} Python
Nim
let variable = collect(initHashSet):
for item in @[-9, 1, 42, 0, -1, 9]: {item}-
collect()requiresimport sugar.
Sets
Python sets are not like Nim set type. If the values that will go in the set are known beforehand and finite, you can create an Enum for them. Otherwise you can emulate a Python set using a HashSet. The Nim set type is faster and memory-efficient. In fact, set is implemented with a bit vector, whereas HashSet is implemented as a dictionary. For simple flag types and small mathematical sets, use set.
Dictionaries
Use Tables for Python dicts.
| Lang | Dictionary | Ordered Dictionary | Counter | Imports |
|---|---|---|---|---|
|
|
dict() |
OrderedDict() |
Counter() |
import collections |
|
|
Table() |
OrderedTable() |
CountTable() |
import tables |
Table Constructors
dict(key="value", other="things") Python
Nim
to_table({"key": "value", "other": "things"})Ordered Dictionary
collections.OrderedDict([(8, "hp"), (4, "laser"), (9, "engine")]) Python
Nim
to_ordered_table({8: "hp", 4: "laser", 9: "engine"})Counters
collections.Counter(["a", "b", "c", "a", "b", "b"]) Python
Nim
to_count_table("abcabb")Examples:
import tables
var dictionary = to_table({"hi": 1, "there": 2})
assert dictionary["hi"] == 1
dictionary["hi"] = 42
assert dictionary["hi"] == 42
assert len(dictionary) == 2
assert dictionary.has_key("hi")
for key, value in dictionary:
echo key, valueTernary operators
"result0" if conditional else "result1" Python
Nim
if conditional: "result0" else: "result1"You probably notice that the Ternary Operator is just an if..else inline.
Reading and writing files
Reading files line by line
with open("yourfile.txt", "r") as f:
for line in f:
print(line)
Python
Nim
for line in lines("yourfile.txt"):
echo line-
lines()Documentation https://nim-lang.org/docs/io.html#lines.i%2Cstring
Read and write files:
write_file("yourfile.txt", "this string simulates data")
assert read_file("yourfile.txt") == "this string simulates data"Read files at compile-time:
const constant = static_read("yourfile.txt") # Returns a string at compile-timeMap & Filter
def isPositive(arg: int) -> bool:
return arg > 0
map(isPositive, [1, 2,-3, 5, -9])
filter(isPositive, [1, 2,-3, 5, -9]) Python
Nim
proc isPositive(arg: int): bool =
return arg > 0
echo map([1, 2,-3, 5, -9], isPositive)
echo filter([1, 2,-3, 5, -9], isPositive)- Map and Filter operations requires
import sequtils.
Lambdas
variable: typing.Callable[[int, int], int] = lambda var1, var2: var1 + var2 Python
Nim
var variable = (proc (var1, var2: int): int = var1 + var2)Anonymous Functions on Nim are basically a function without a name and surrounded by parens.
Decorators
- Templates and Macros can be used similar to Python Decorators.
def decorator(argument):
print("This is a Decorator")
return argument
@decorator
def function_with_decorator() -> int:
return 42
print(function_with_decorator())
Python
Nim
template decorator(argument: untyped) =
echo "This mimics a Decorator"
argument
func function_with_decorator(): int {.decorator.} =
return 42
echo function_with_decorator()- Why Nim wont use
@decoratorsyntax?.
Nim uses {. and .} because it can have several decorators together.
Also Nim one works on variables and types:
func function_with_decorator(): int {.discardable, inline, compiletime.} =
return 42
let variable {.compiletime.} = 1000 / 2
type Colors {.pure.} = enum Red, Green, BlueJSON
Python uses multi-line strings with JSON inside, Nim uses literal JSON directly on the code.
import json
variable = """{
"key": "value",
"other": true
}"""
variable = json.loads(variable)
print(variable) Python
Nim
import json
var variable = %*{
"key": "value",
"other": true
}
echo variable-
%*converts everything inside the braces to JSON, JSON has a typeJsonNode. -
%*can have variables and literals inside the braces. - JSON can have comments inside the braces of
%*, Nim kind of comments. - If the JSON is not valid JSON the code will not compile.
-
JsonNodecan be useful on Nim because is a type that can have mixed types and grow/shrink. - You can read JSON at compile-time, and store it on a constant as string.
- To parse JSON from string you can use
parseJson("{}"). - To parse JSON from a file
parseFile("file.json"). - JSON documentation
Self-Execution of Main Module
if __name__ == "__main__":
main() Python
Nim
when is_main_module:
main()Unittests
import unittest
def setUpModule():
"""Setup: Run once before all tests."""
pass
def tearDownModule():
"""Teardown: Run once after all tests."""
pass
class TestName(unittest.TestCase):
"""Test Name"""
def setUp(self):
"""Setup: Run once before each tests."""
pass
def tearDown(self):
"""Teardown: Run once after each test."""
pass
def test_example(self):
self.assertEqual(42, 42)
if __name__ == "__main__":
unittest.main()
Python
Nim
import unittest
suite "Test Name":
echo "Setup: Run once before all tests."
setup:
echo "Setup: Run once before each test."
teardown:
echo "Teardown: Run once after each test."
test "example":
assert 42 == 42
echo "Teardown: Run once after all tests."- Unittest documentation.
- Nimble the package manager can also run Unittests.
- NimScript can also run Unittests.
-
You can run documentation as Unittests with
runnableExamples. - Testament is a more advanced Unittests runner.
DocStrings
DocStrings on Nim are ReSTructuredText and MarkDown comments starting with ##,
notice ReSTructuredText and MarkDown can be mixed together if you want.
Generate HTML, Latex (PDF) and JSON documentation from source code with nim doc file.nim.
Nim can generate a dependency graph DOT .dot file with nim genDepend file.nim.
You can run documentation as Unittests with runnableExamples.
""" Documentation of Module """
class Kitten(object):
""" Documentation of Class """
age: int
def purr(self):
""" Documentation of function """
print("Purr Purr") Python
Nim
## Documentation of Module *ReSTructuredText* and **MarkDown**
type Kitten = object ## Documentation of Type *ReSTructuredText* and **MarkDown**
age: int ## Documentation of Attribute *ReSTructuredText* and **MarkDown**
proc purr(self: Kitten) =
## Documentation of Function *ReSTructuredText* and **MarkDown**
echo "Purr Purr"Optional Indentation
For short lines you can write the code on a single line, inline constructs without errors or warnings.
let a = try: 1 + 2 except: 42 finally: echo "Inline Try"
let b = if true: 2 / 4 elif false: 4 * 2 else: 0
for i in 0..9: echo i
proc foo() = echo "Function"
(proc () = echo "Anonimous Function")()
template bar() = echo "Template"
macro baz() = echo "Macro"
var i = 0
while i < 9: i += 1
when is_main_module: echo 42CamelCase
- Why Nim is CamelCase instead of snake_case?.
It really isn't, Nim is Style Agnostic.
let camelCase = 42 # Declaring as camelCase
assert camel_case == 42 # Using as snake_case
let snake_case = 1 # Declaring as snake_case
assert snakeCase == 1 # Using as camelCaseThis feature allows Nim to seamlessly interoperate with a lot of programming languages with different styles.
For more homogeneous code a default is chosen, and can even be enforced if you want,
to enforce the default code style you can add to the compile command --styleCheck:hint,
Nim will style check your code before compilation, similar to pycodestyle on Python,
if you want even more strict style you can use --styleCheck:error.
A lot of programming languages have some kind of Case Insensitivity, such as: PowerShell, SQL, PHP, Lisp, Assembly, Batch, ABAP, Ada, Visual Basic, VB.NET, Fortran, Pascal, Forth, Cobol, Scheme, Red, Rebol.
If you are just starting from scratch, you can use Python like names while learning, it will not produce an error for doing so, until you learn more.
def Vs proc/func
- Why Nim wont use
definstead ofproc?.
Nim is uses proc for normal functions from "Procedure" naming.
Uses func for Functional Programming side-effect free functions like from "mathematical functions".
Nim has side-effects tracking.
- Why Nim wont use
async def?.
Async is just a macro on Nim, no need to change the syntax of the language, is like a Decorator on Python.
Also on Nim the same function can be Async and Sync at the same time, with the same code, with the same name.
If you are just starting from scratch, you can use proc for all the functions while learning,
it will not produce an error for doing so, until you learn more.
Do I have to know C?
You never have to actually manually edit C, the same way on Python you never manually edit the PYC files.
On Nim you code by writing Nim, the same way on Python you code writing Python.
Templates
Templates replace its invocation with its content body at compile-time.
Imagine it like the compiler will copy&paste a chunk of code for you.
Template allows to have a function-like constructs without any overheads, allows you to split huge functions into smaller constructs.
Too much function names and variable names may pollute and saturate the local namespace, variables inside templates do not exist outside of its template, templates do not exist on the namespace at run-time (if you do not export it), templates may optimize certain values if they are known at compile-time.
Templates allows you to implement a very high-level beautiful API for everyday usage, while keeping the low-level optimized stuff out of your head and DRY.
Python with open("file.txt", mode = "r") as file: implemented using 1 template:
GIF is not perfect, but a lazy simplified approximation!.
This is not the way to read files on Nim, just an exercise.
Template is not perfect, but a lazy approximation!, exercise for the reader to try to improve it ;P
template with_open(name: string, mode: char, body: untyped) =
let flag = if mode == 'w': fmWrite else: fmRead # "flag" dont exist outside of this template
let file {.inject.} = open(name, flag) # Create and inject "file" variable, "file" variable exists outside of this template because {.inject.}
body # "body" is code passed as argument
file.close() # Code after code passed as argument
with_open("testin.nim", 'r'): # Mimic Python with open("file", mode='r') as file
echo "Hello Templates" # Code inside the template, this 2 lines are "body" argument on the template
echo file.read_all() # This line uses "file" variableIf you are just starting from scratch, do not worry, you can use Functions for everything while learning.
How to share variables between functions?
Sharing variables between functions is similar to Python.
Global variable:
global_variable = ""
def function0():
global_variable = "cat"
def function1():
global_variable = "dog"
function0()
assert global_variable == "cat"
function1()
assert global_variable == "dog"
function0()
assert global_variable == "cat" Python
Nim
var global_variable = ""
proc function0() =
global_variable = "cat"
proc function1() =
global_variable = "dog"
function0()
assert global_variable == "cat"
function1()
assert global_variable == "dog"
function0()
assert global_variable == "cat"Object Attribute:
class IceCream(object):
object_attribute: int
def functiona(food: IceCream):
food.object_attribute = 9
def functionb(food: IceCream):
food.object_attribute = 5
food = IceCream()
functiona(food)
assert food.object_attribute == 9
functionb(food)
assert food.object_attribute == 5
functiona(food)
assert food.object_attribute == 9 Python
Nim
type IceCream = object
object_attribute: int
proc functiona(food: var IceCream) =
food.object_attribute = 9
proc functionb(food: var IceCream) =
food.object_attribute = 5
var food = IceCream()
functiona(food)
assert food.object_attribute == 9
functionb(food)
assert food.object_attribute == 5
functiona(food)
assert food.object_attribute == 9You can pass functions as argument of functions like in Python too.
Import Nim files on Python
Python Syntax for Nim
Publish to PYPI
Silent Compilation
If you want the compilation to be completely silent (you may miss important warnings and hints),
you can add to the compile command --hints:off --verbosity:0.
Compiler Help
The Compiler help is long, to make it more user friendly only the most frequent commands are shown with --help,
if you want to see the full help you can use --fullhelp.
Build Modes
When your code is ready for production you should use a Release build,
you can add to the compile command -d:release.
| Feature | Release Build | Debug Build |
|---|---|---|
| Speed | Fast | Slow |
| File Size | Small | Big |
| Optimized | ||
| Tracebacks | ||
| Run-time checks | ||
| Compile-time checks | ||
assert |
||
doAssert |
MicroPython
Nim compiles to C, so it can run on Arduino and similar hardware.
Has several memory management strategies to fit your needs, including full manual memory management. Nim binaries are small when built for Release and it can fit the hardware tiny storage.
- https://github.com/zevv/nim-arduino
- https://gitlab.com/endes123321/nimcdl/tree/master#nimcdl-nim-circuit-design-language
- https://github.com/cfvescovo/Arduino-Nim#arduino-nim
- https://gitlab.com/nimbed/nimbed#nimbed
- https://gitlab.com/endes123321/led-controller-frontend#led-controller-frontend
SuperCollider
SuperCollider is C++ so it can be re-utilized using Nim.
Theoretically, Nim SuperCollider plugins should be just as fast as C code. Nim metaprogramming allows to build LiveCoding friendly DSLs.
Some projects for Nim LiveCoding:
- https://github.com/vitreo12/omni#omni
- https://github.com/capocasa/scnim#scnim---writing-supercollider-ugens-using-nim
ABC
See this
Philosophy
The key to understanding Nim is that Nim was designed to be as fast as C, but to be much safer. Many of the design-decisions are based on making it harder to shoot yourself in the foot. In Python there are no pointers (everything is treated as a reference). While Nim does give you pointers, Nim gives you other, safer tools for your everyday needs, while pointers are mostly reserved for interfacing with C and doing low-level system programming.
Contrarily to Python, most Nim code can be executed at compile time to perform meta-programming. You can do a lot of the DSLs possible with Python decorators / metaprogramming with Nim macros and pragmas. (And some stuff that you can't!). Of course this requires some different patterns and more type safety.
