Version 0.18.0 released

The Nim team is happy to announce that the latest release of Nim, version 0.18.0, is now available. Nim is a systems programming language that focuses on performance, portability and expressiveness.

Installing 0.18.0

If you have installed a previous version of Nim using choosenim , getting Nim 0.18.0 is as easy as:

$ choosenim update stable

If you don’t have it already, you can get choosenim by following these instructions or you can install Nim manually by following the instructions on our install page. Note that Windows users might still have an easier time with the unzip+finish.exe method of installing Nim which is described on the install page.

What’s new in 0.18.0

It’s been a while since our last release, but we’ve been busy. At over 1000 commits since the last release, v0.18.0 is one of (if not the) biggest releases of Nim ever.

We have mentioned multiple times that this will be a major release. Primarily because our goal has been to clean up the standard library significantly in preparation for v1.0. We’ve made massive progress in this release to achieve that goal. The downside is that this release has a much larger proportion of breaking changes than normal releases, but it is all in the spirit of a cleaner Nim v1.0.

Breaking changes to be mindful of

You will find that the [] indexing operator which takes a slice now raises an IndexError exception when it is out of bounds. Previously it would have simply returned the part of the string that was captured. You may find that your program hasn’t taken this into account and will now crash with an IndexError exception. To get back the previous behaviour, use the substr procedure. Here is an example of the issue and how to get around it:

var myString = "hello world" doAssertRaises IndexError : discard myString [ 6 .. 45 ] doAssert myString . substr ( 6 , 45 ) == "world"

The $ operator now handles collections differently. For example:

doAssert $ ( @[ "23" , "12" ] ) == "@[ \" 23 \" , \" 12 \" ]" # Whereas in 0.17.2: doAssert $ ( @[ "23" , "12" ] ) == "@[23, 12]"

An array[x, char] can no longer be converted to a cstring type. This has the side-effect of allowing $ to be defined on an array:

var x : array [ 5 , char ] doAssert $ x == r"['\x00', '\x00', '\x00', '\x00', '\x00']"

Be sure to check out the changelog below for a comprehensive list of breaking changes. If you run into any strange regressions feel free to pop into IRC, Gitter, Discord or any of the other chat rooms/forums we have available. Links to them all are available in our community page.

New features

Of course, this being a major new release, there are also plenty of new features.

Formatted string literals

The greatest new addition is the strformat module. It implements string formatting that is very similar to Python 3’s f-strings.

Formatted string literals are prefixed with fmt or the & operator:

import strformat let name = "Fred" let age = 24 let weight = 94.52 doAssert fmt"My name is {name}. I'm {age} years of age and weigh {weight:.3f}." == "My name is Fred. I'm 24 years of age and weigh 94.520."

For more information, take a look at the strformat documentation.

Testable documentation examples

The documentation generator can now test your examples for you! This is done using the new runnableExamples macro.

proc add * ( x , y : int ): int = ## Adds two numbers together. ## ## Examples: ## runnableExamples : doAssert add ( 5 , 5 ) == 10 doAssert add ( - 5 , 2 ) == - 3 x + y

If you save this as addLib.nim and then generate its documentation via nim doc addLib.nim , you should see something like this:

Hint: /tmp/addLib_examples [Exec] Hint: operation successful (13129 lines compiled; 0.492 sec total; 19.742MiB peakmem; Debug Build) [SuccessX]

The code under runnableExamples will be embedded in the procedure’s documentation.

If your examples have an error in them then you will see it, together with a stack trace if your error occurs at runtime. This is great for ensuring that your documentation is up-to-date.

mapLiterals

This is a new macro that allows you to easily create array and sequence literals.

import sequtils let x = mapLiterals ( [ 12 , 34 , 15 , 1 ] , uint32 ) doAssert x is array [ 4 , uint32 ]

New memory manager algorithm

The new TLSF algorithm has been implemented to reduce memory fragmentation. This has a side effect of making alloc and dealloc O(1) operations.

Async improvements

There have been a number of various improvements to the asynchronous IO modules in the stdlib. There is no longer an “upcoming” and standard asyncdispatch split, the former was merged and is now the default asyncdispatch implementation.

A new getIoHandler procedure is now available, it returns a handle to the underlying IO completion port or epoll/kqueue fd used by asyncdispatch. Main advantage of this is that libraries now have even greater control over the event loop. As an example, it allows much more efficient HTTP server implementations (one such implementation is called httpbeast).

A new implementation of async await has also been added for the JavaScript backend in the asyncjs module.

Nimble v0.8.10

In the release are also updates to the Nim package manager. The latest version of Nimble is included and contains multiple new features and bug fixes.

The major new feature is the support for multiple Nimble packages in a single Git/Hg repository.

Check out the changelog for a list of changes since Nimble’s last release.

Contributors to v0.18.0

Our contributors are amazing, and there is far too many to list here. Big thanks to all of you, we couldn’t have pulled off this release without you!

Changelog

Changes affecting backwards compatibility

Breaking changes in the standard library

The [] proc for strings now raises an IndexError exception when the specified slice is out of bounds. See issue #6223 for more details. You can use substr(str, start, finish) to get the old behaviour back, see this commit for an example.

strutils.split and strutils.rsplit with an empty string and a separator now returns that empty string. See issue #4377.

Arrays of char cannot be converted to cstring anymore, pointers to arrays of char can! This means $ for arrays can finally exist in system.nim and do the right thing. This means $myArrayOfChar changed its behaviour! Compile with -d:nimNoArrayToString to see where to fix your code.

reExtended is no longer default for the re constructor in the re module.

The behavior of $ has been changed for all standard library collections. The collection-to-string implementations now perform proper quoting and escaping of strings and chars.

newAsyncSocket taking an AsyncFD now runs setBlocking(false) on the fd.

mod and bitwise and do not produce range subtypes anymore. This turned out to be more harmful than helpful and the language is simpler without this special typing rule.

formatFloat / formatBiggestFloat now support formatting floats with zero precision digits. The previous precision = 0 behavior (default formatting) is now available via precision = -1 .

Moved from stdlib into Nimble packages: basic2d deprecated: use glm , arraymancer , neo , or another package instead basic3d deprecated: use glm , arraymancer , neo , or another package instead gentabs libuv polynumeric pdcurses romans libsvm joyent_http_parser

Proc toCountTable now produces a CountTable with values corresponding to the number of occurrences of the key in the input. It used to produce a table with all values set to 1 . Counting occurrences in a sequence used to be: let mySeq = @[ 1 , 2 , 1 , 3 , 1 , 4 ] var myCounter = initCountTable [ int ] () for item in mySeq : myCounter . inc item Now, you can simply do: let mySeq = @[ 1 , 2 , 1 , 3 , 1 , 4 ] myCounter = mySeq . toCountTable ()

If you use --dynlibOverride:ssl with OpenSSL 1.0.x, you now have to define openssl10 symbol ( -d:openssl10 ). By default OpenSSL 1.1.x is assumed.

newNativeSocket is now named createNativeSocket .

newAsyncNativeSocket is now named createAsyncNativeSocket and it no longer raises an OS error but returns an osInvalidSocket when creation fails.

The securehash module is now deprecated. Instead import std / sha1 .

The readPasswordFromStdin proc has been moved from the rdstdin to the terminal module, thus it does not depend on linenoise anymore.

Breaking changes in the compiler



is now only the single line feed character like in most other programming languages. The new platform specific newline escape sequence is written as \p . This change only affects the Windows platform.

The overloading rules changed slightly so that constrained generics are preferred over unconstrained generics. (Bug #6526)

We changed how array accesses “from backwards” like a[^1] or a[0..^1] are implemented. These are now implemented purely in system.nim without compiler support. There is a new “heterogeneous” slice type system.HSlice that takes 2 generic parameters which can be BackwardsIndex indices. BackwardsIndex is produced by system.^ . This means if you overload [] or []= you need to ensure they also work with system.BackwardsIndex (if applicable for the accessors).

The parsing rules of if expressions were changed so that multiple statements are allowed in the branches. We found few code examples that now fail because of this change, but here is one: t [ ti ] = if exp_negative : '-' else : '+' ; inc ( ti ) This now needs to be written as: t [ ti ] = ( if exp_negative : '-' else : '+' ); inc ( ti )

The experimental overloading of the dot . operators now take an untyped parameter as the field name, it used to be a static[string] . You can use when defined(nimNewDot) to make your code work with both old and new Nim versions. See special-operators for more information.

yield (or await which is mapped to yield ) never worked reliably in an array, seq or object constructor and is now prevented at compile-time.

Library additions

Added sequtils.mapLiterals for easier construction of array and tuple literals.

Added system.runnableExamples to make examples in Nim’s documentation easier to write and test. The examples are tested as the last step of nim doc .

Implemented getIoHandler proc in the asyncdispatch module that allows you to retrieve the underlying IO Completion Port or Selector[AsyncData] object in the specified dispatcher.

For string formatting / interpolation a new module called strformat has been added to the stdlib.

The ReadyKey type in the selectors module now contains an errorCode field to help distinguish between Event.Error events.

Implemented an accept proc that works on a SocketHandle in nativesockets .

Added algorithm.rotateLeft .

Added typetraits.$ as an alias for typetraits.name .

Added system.getStackTraceEntries that allows you to access the stack trace in a structured manner without string parsing.

Added parseutils.parseSaturatedNatural .

Added macros.unpackVarargs .

Added support for asynchronous programming for the JavaScript backend using the asyncjs module.

Added true color support for some terminals. Example: import colors , terminal const Nim = "Efficient and expressive programming." var fg = colYellow bg = colBlue int = 1.0 enableTrueColors () for i in 1 .. 15 : styledEcho bgColor , bg , fgColor , fg , Nim , resetStyle int -= 0.01 fg = intensity ( fg , int ) setForegroundColor colRed setBackgroundColor colGreen styledEcho "Red on Green." , resetStyle

Library changes

echo now works with strings that contain \0 (the binary zero is not shown) and nil strings are equal to empty strings.

JSON: Deprecated getBVal , getFNum , and getNum in favour of getBool , getFloat , getBiggestInt . A new getInt procedure was also added.

rationals.toRational now uses an algorithm based on continued fractions. This means its results are more precise and it can’t run into an infinite loop anymore.

os.getEnv now takes an optional default parameter that tells getEnv what to return if the environment variable does not exist.

The random procs in random.nim have all been deprecated. Instead use the new rand procs. The module now exports the state of the random number generator as type Rand so multiple threads can easily use their own random number generators that do not require locking. For more information about this rename see issue #6934

writeStackTrace is now proclaimed to have no IO effect (even though it does) so that it is more useful for debugging purposes.

db_mysql module: DbConn is now a distinct type that doesn’t expose the details of the underlying PMySQL type.

parseopt2 is now deprecated, use parseopt instead.

Language additions

It is now possible to forward declare object types so that mutually recursive types can be created across module boundaries. See package level objects for more information.

Added support for casting between integers of same bitsize in VM (compile time and nimscript). This allows to, among other things, reinterpret signed integers as unsigned.

Custom pragmas are now supported using pragma pragma , please see language manual for details.

Standard library modules can now also be imported via the std pseudo-directory. This is useful in order to distinguish between standard library and nimble package imports: import std / [ strutils , os , osproc ] import someNimblePackage / [ strutils , os ]

Language changes

The unary < is now deprecated, for .. < use ..< for other usages use the pred proc.

Bodies of for loops now get their own scope: # now compiles: for i in 0 .. 4 : let i = i + 1 echo i

To make Nim even more robust the system iterators .. and countup now only accept a single generic type T . This means the following code doesn’t die with an “out of range” error anymore: var b = 5. Natural var a = - 5 for i in a .. b : echo i

atomic and generic are no longer keywords in Nim. generic used to be an alias for concept , atomic was not used for anything.

The memory manager now uses a variant of the TLSF algorithm that has much better memory fragmentation behaviour. According to http://www.gii.upv.es/tlsf/ the maximum fragmentation measured is lower than 25%. As a nice bonus alloc and dealloc became O(1) operations.

The compiler is now more consistent in its treatment of ambiguous symbols: Types that shadow procs and vice versa are marked as ambiguous (bug #6693).

codegenDecl pragma now works for the JavaScript backend. It returns an empty string for function return type placeholders.

Extra semantic checks for procs with noreturn pragma: return type is not allowed, statements after call to noreturn procs are no longer allowed.

Noreturn proc calls and raising exceptions branches are now skipped during common type deduction in if and case expressions. The following code snippets now compile: import strutils let str = "Y" let a = case str : of "Y" : true of "N" : false else : raise newException ( ValueError , "Invalid boolean" ) let b = case str : of nil , "" : raise newException ( ValueError , "Invalid boolean" ) elif str . startsWith ( "Y" ): true elif str . startsWith ( "N" ): false else : false let c = if str == "Y" : true elif str == "N" : false else : echo "invalid bool" quit ( "this is the end" )

and expressions. The following code snippets now compile: Pragmas now support call syntax, for example: {.exportc"myname".} and {.exportc("myname").}

The deprecated pragma now supports a user-definable warning message for procs. proc bar {. deprecated : "use foo instead" .} = return bar ()

Tool changes

The nim doc command is now an alias for nim doc2 , the second version of the documentation generator. The old version 1 can still be accessed via the new nim doc0 command.

Nim’s rst2html command now supports the testing of code snippets via an RST extension that we called :test: :: .. code-block:: nim :test: # shows how the 'if' statement works if true: echo "yes"

Bugfixes