Hacker News new | past | comments | ask | show | jobs | submit login

> “It prefers the stack so strongly that dynamic data structures (sequences and tables, basically its lists and dictionaries) are pointers on the stack to heap data, where the lifetime is managed by the stack frame.”

Isn’t that the same as a C++ vector or map on stack? They allocate internally as needed, and the whole container is destroyed when it goes out of scope.




It very much is, and the point is, it _used_ to be more like java. Araq basically pulled off a very daring switchover from reference based language system to a value based one.

So now the language can credibly claim the same as c++ - no room left closer to the metal. But it's packaged in a much nicer syntax (imho), and has features like macros which we can expect I'm C++ in maybe 10 years, if we're lucky.


Basically, but it requires no extra syntax. `var some_seq = @[1, 2, 3, 4]` is a stack-managed sequence. That's all there is to it. There's no unwrapping any pointers or boxes or what-not, the type is just `seq[int]`. Put another way, things that have become best practice in C++ are default in Nim with no syntactic noise.


There's no unwrapping any pointers or boxes or what-not

That doesn't happen by default in C++ either.

std::vector<int> some_seq{1, 2, 3, 4, 5, 7};


or even just

     std::vector some_seq{1, 2, 3, 4, 5, 7}; 
nowadays (for a value of nowadays that is 5 years old for GCC and 6 years old for Clang)


Indeed there's no question that Nim is basically following C++'s lead on this. Nim iirc always had constructors and destructors. Final piece of the puzzle is move semantics, and I recall a blog post where Araq came up with something very similar.


yes, Nim has move semantics, but takes care of you more than c++ does. for example, if you use an object that was previously moved, you dont get garbage, the compiler turns the first move into a copy (and tells you)

the relevant docs are here: https://nim-lang.org/docs/destructors.html


Agreed, only being able to put pointers on the stack, no data, would make me think it "prefers the heap".


Dynamic data structures by their nature have to be allocated to the heap. What I mean by "prefers the stack" is that you don't have to make a managed ref and dereference a managed pointer type. You just make a `seq[int]`, use it as a `seq[int]`, and pass it as a `seq[int]`, just like stack data. Behind the scenes, it has a unique scoped pointer with no mental overhead.


Sounds like a vector/array/list in any other language after C++, like Go slice, Java ArrayList, Javascript array, Python list, Rust vec. Is there something I'm missing?


I think they're discussing the lifetime of that heap data, not whether the data is heap allocated.


I don't see them drawing any distinctions from C++ or Rust there either. It really sounds to me like most of their low-level experience is in C, where the contrasts they appear to be drawing really do apply.


it depends on what you mean by 'dynamic' and 'stack'; certainly, outside of nim, you can allocate a list of, say, integers entirely on a stack in any of the following cases:

- the size of the list is known when you create a stack frame, as in c:

    int xs[n] = {0};
- when the list grows, it grows in that subroutine and not some callee, for example using alloca();

- the list is built on a stack that isn't the one you have to pop your return address off of; examples include perl's data stack, ada's secondary stack, forth's operand stack, forth's dictionary, or an mlkit region. in these cases you can even return the dynamically built structure to a caller;

- each new callee adds some fixed number of items to a linked list, such as, in c

    void with_fill(color *c, 
        env *e, 
        void (*cb)(void*, env*), 
        void *userdata)
    {
      env ne = {
        .prop = PROP_FILL_COLOR,
        .val = c,
        .parent = e };
      cb(userdata, &ne);
    }
look ma, no heap


Types are stack allocated by default.

"var data: MyObject" is on the stack. "var arr: array[1000, MyObject]" is allocated on the stack sequentially.

Only dynamic seq or ref types use the heap by default.


So, same as C++.


Same as Rust. Vec and HashMap are stack pointers to the heap-allocated container storage space.




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: