
Pointer Free Programming and the Future of Nim - mindB
https://nim-lang.org/araq/destructors.html
======
dom96
Hello guys. I'm one of the core Nim developers, together with Araq (the
creator of Nim) who should also be hanging around this thread. Feel free to
ask us anything.

This submission is likely the result of the recent livestreams that myself and
Araq have been making. You can check out my past livestreams[1] and Araq's[2]
at the links below. If you're into watching us live the next time we create a
livestream then follow d0m96
([https://go.twitch.tv/d0m96](https://go.twitch.tv/d0m96)) and araq4k
([https://go.twitch.tv/araq4k](https://go.twitch.tv/araq4k)) on Twitch.

1 -
[https://www.youtube.com/watch?v=UQ4RvUlXIDI&index=3&list=PLm...](https://www.youtube.com/watch?v=UQ4RvUlXIDI&index=3&list=PLm-
fq5xBdPkrMuVkPWuho7XzszB6kJ2My)

2 -
[https://www.youtube.com/watch?v=E2qlDKm_WzE](https://www.youtube.com/watch?v=E2qlDKm_WzE),
[https://www.youtube.com/watch?v=UV38gQfcb9c](https://www.youtube.com/watch?v=UV38gQfcb9c)

~~~
qaq
You guys are doing amazing work! Found Nim through a mention on HN recently
and having a ton of fun learning and playing with it!

~~~
athenot
Same here. Nim has this elegance that is hard to qualify and impossibe to
quantify, but it makes it a real pleasure to write code in it. Can't wait to
get deeper into it.

------
pavlov
I’m not a huge fan of the modern C++ style that obsessively avoids null
pointers and instead uses object references that are created in an
invalid/empty state. With a pointer there is a single way to represent
“nothing”, regardless of what the object represents. With a reference I have
to go read the API to understand the “nothingness” states.

Also, when you’re thinking in pointers, it’s easy to add levels of indirection
with the same mental tools (pointers to pointers, etc.) Personally I find it’s
easier to solve problems with a limited orthogonal toolset than a sprawling
array of marginally differently balanced optimizations, which is what most of
C++ has become.

~~~
jstimpfle
I don't get the buzz about null pointers. They are not a problem. They become
a problem when you start checking for null where null is not acceptable (most
of the places null can't be a meaningful input), which is where is where the
original intent starts to become unclear.

Let it go. Let it crash. Just assume inputs are non-null (except where null
makes sense). Even C crashes safely on null pointer dereference.

~~~
IshKebab
The problem is that the type system doesn't encode whether a point _can_ be
null or not, so unless your documentation is amazing (I doubt it) you'll
eventually end up getting passed a pointer from someone else, or giving a
pointer to someone else who has a different assumption about whether null is
allowed. Boom segfault.

There are several solutions in C++.

1\. Always check for null. Kind of annoying and lots of people don't for
whatever reason.

2\. Use references. As you say, annoying because then you _can 't_ have null
(sensibly) even when it would be really useful.

3\. Use std::optional<int&> or something like that. I only just thought of
this and don't know if it would work, but I bet it's a pain.

So no great solution. Personally I would use a smart pointer type, document it
as well as I can, and always check for null.

~~~
jstimpfle
> so unless your documentation is amazing

As I pointed out I usually don't have null pointers at all. There might be a
few places where a value can very obviously be null, but they are far and far
between. No need for documentation.

> Boom segfault.

Which is exactly the right thing to happen (it's the C version of Exceptions
in dynamic languages) since the code was incorrect.

> Always check for null. Kind of annoying and lots of people don't for
> whatever reason.

And now what do you do if you detected null but it was not allowed? Throw an
exception? You can have that for free by just not checking.

> Use references. As you say, annoying because then you can't have null
> (sensibly) even when it would be really useful.

C++ references don't really protect you from NULL. It's just a different
syntax for the same thing.

> Use std::optional<int&> or something like that. I only just thought of this
> and don't know if it would work, but I bet it's a pain.

Yes, pain, big pain. So much line noise and typing (in both senses) around
what is essentially an int.

Just don't check. I don't get why there's so many places for null pointers.
(As I said elsewhere, I don't have a solution for JSON style microscopic
programming, and I don't care about that.).

~~~
palunon
How do C++ references not protect you from NULL ?

From the standard:

> A reference shall be initialized to refer to a valid object or function.
> [Note: in particular, a null reference cannot exist in a well-defined
> program, because the only way to create such a reference would be to bind it
> to the “object” obtained by dereferencing a null pointer, which causes
> undefined behavior. As described in 9.6, a reference cannot be bound
> directly to a bit-field. ]

~~~
jstimpfle
Better try instead of reading standards (and inevitably misreading, or reading
differently than compiler authors)...

    
    
        #include <stdio.h>
        void test(int& x)
        {
            printf("Hello, world\n"); fflush(stdout);
            printf("and the number is: %d\n", x);
        }
        int main(void)
        {
            int *x = NULL;
            test(*x);
            return 0;
        }
    

It's just a syntactic discipline. Null references are undefined in C++, just
as NULL dereferences are undefined in C.

------
tempodox
Completely off-topic, bit I feel compelled to mention this: The timestamping
of this article is exemplary.

Even if it only showed a date, and no time, the time zone is relevant. The
Internet is supposed to be for the whole world, not just one time zone.

------
audunw
Does this mean that Nim 1.0 will be postponed even further?

That's OK, it's better to get it right, and it's still useful for small
projects in the meantime. But Nim seems like a language that is never truly
finished.

I like this direction. I tried to avoid "ref" in my last Nim project, but it's
too hard to do that for every type the way the language is currently designed.

~~~
Tiberium
It won't be postponed AFAIK

~~~
dom96
Indeed, Araq's plan is to release v1 ASAP (he said by the end of this year on
IRC) and implement the ideas described in this article afterwards for a Nim
v2.

------
seertaak
I'm a C++ dev and this sounds extremely interesting. I have nim a spin a year
ago and really liked what I saw, but GC was a real issue because I'm doing
audio development where you end up having to circumvent the GC anyway. I would
love to allow my users to create MIDI plugins with nim and this is a key step
towards that.

~~~
mratsim
I'd like to add that "circumventing the GC" is supported by default. There are
3 object types in Nim

\- `type Foo = object` --> Value type, on the stack

\- `type Foo = ref object` --> Reference type, managed by GC

\- `type Foo = ptr object` --> Pointer type, manual memory management (with
Nim's equivalent for malloc, free and memcopy)

Also Nim does not have 1 GC but several:

\- Default Deferred Reference Counting - Not stop the world

\- Boehm GC

\- Mark and Sweep

\- Memory Regions

\- Real-time GC (with tunable max-pause)

\- GC disabled

GC can also be deactivated per thread (setupForeignThreadGc) or for a section
of the code (GC_ref, GC_unref) even on Ref types to improve interoperability
with other languages.

------
userbinator
The syntax and title reminds me of standard Pascal, which has very constrained
pointers that, among other things, you can't do arithmetic with --- eventually
leading to code that basically reinvents memory itself by using a large array
and lots of indexing operations.

(Look at Donald Knuth's TeX for an example of this style.)

~~~
mratsim
Nim was written in Pascal at the very beginning.

But you can't do pointer arithmetics in Nim.

Either

\- `type Foo = object` -> Value type, on the stack

\- `type Foo = ref object` -> Ref type, managed by GC

\- `type Foo = ptr object` -> Pointer type, manual memory management (malloc,
free, memcopy ...)

~~~
dom96
> But you can't do pointer arithmetics in Nim.

Actually you can, by using casts.

~~~
mratsim
Oops, I obviously meant "you can" but I probably typed too fast :P

------
duneroadrunner
First let me say that I'm not familiar with Nim. But I understand that it
compiles/transpiles to C/C++. And it sounds like they're now trying to move
away from dependency on the GC. In that case, might I suggest they consider
switching the transpile target to SaferCPlusPlus[1]. It might make things
easier as it already addresses the "efficient memory-safety via scope
lifetimes without a borrow-checker" issue. And also the (data race) safe
sharing of objects between threads. (Note that the documentation is currently
rather out-of-date, and a major update is coming.)

[1] shameles plug:
[https://github.com/duneroadrunner/SaferCPlusPlus](https://github.com/duneroadrunner/SaferCPlusPlus)

~~~
mratsim
Nim compiles to C/C++/Objective-C and Javascript and all memory safety is
handled on the Nim side.

The C/C++ code generated by the Nim compiler is then free to use unsafe
constructs including the dreaded goto.

------
jamesu
The other year I tried to implement a GC on top of an existing scripting
language to handle circular dependency cases. A big problem however was the
existing system for referencing objects wasn't particularly well designed for
this particular case (e.g. no roots, no thread safety), and I couldn't come up
with a solution I found satisfactory and fool-proof.

The fact the author had so many problems with GC bugs is somewhat reassuring.
Would be interesting to see a GC-less Nim in a production use-case.

------
tomsmeding
That sink concept sounds _really_ cool. I would really want that semantic in
my C and C++ code.

~~~
Boxxed
Pretty sure that's the semantics of an `auto_ptr`:
[http://www.cplusplus.com/reference/memory/auto_ptr/](http://www.cplusplus.com/reference/memory/auto_ptr/)

------
ndh2
Suggestion: Add a date, the author, and possibly some version number that
indicate what iteration of Nim this refers to.

