> Goose looks familiar like C or Rust, and is built on one idea: there is no heap
So it looks like it restricts the memory management to 100% scope based. I expect that makes a lot of designs for programs not translate to it as well as they fit in Rust or Java (for example). There are a bunch more constraining design choices they list further down:
> - Nothing ever moves
> - ... A string, an array of strings, a record with variable-size fields and an array of those records are each one contiguous block with no pointer in it
I'll have to look a bit deeper to decide if it's feasible to write many things in this language.
Not the OP, but I'm thinking about like closures?
Say you wanted to make a Node.js framework with callbacks that react to an event. The callback might be a closure that captured some of its surrounding variables. At that point, any of the captured variables are not trivially stack-allocated.
You might be able to do something similar to what Rust does with moving though.
You could predefine your event handlers within your context, then call 'enter framework' and pass your event handlers as arguments. this is continuation passing style
Nah we did something similar on Microsoft Band. I wrote about how - <a href="https://meanderingthoughts.hashnode.dev/cooperative-multitasking-on-microsoft-band" rel="nofollow">https://meanderingthoughts.hashnode.dev/cooperative-multitas...
The tldr is you had to preallocate a struct with anything you wanted captured ahead of time.
Typically you would construct this state in statically allocated memory. A lot of systems work this way. Dynamic heap allocation isn’t the only alternative to stack allocation.
Say you wanted a map of some key to growable arrays (or maps), where the number of keys isn't known until runtime. It I understand correctly, you can't really do that because the number of growable stacks nees to be known at compile time.
Might as well go back to ye olden days and put 100% of your memory in a giant preallocated block and instead of stack locals you just use the block. No allocation cost at runtime, cheese benchmarks by making the super arena.
> Might as well go back to ye olden days and put 100% of your memory in a giant preallocated block
I do that for the Playdate: statically allocate most of the large structures and tables in global variables, and don't call malloc or free after initialization is done.
I also put some things on the stack, not so much because I need to dynamically allocate or free something, often it's because I get lower access latency to the stack compared to main memory (because stack lives inside ARM's tightly coupled memory).
There are languages with first class continuations, is if every function is async and every call is await. In that context, everything can be stack allocated and every reference to stack memory stays valid always. The cost is that stack is now non-linear / not a contiguous array.
Dynamic memory management is a performance enhancement. It lets you more efficiently utilize memory vs static allocation at the cost of, well, lots of types of bugs.
You can always preallocate MAX_NUM_ELEMENTS * SIZE_OF_OBJECT for all your arrays. If someone tries to send you more objects then you have buffer space for you just reject the request.
Latency sensitive programs already do this, since memory allocation is rarely deterministic (although it can be in .NET and other similar languages). Likewise a bunch of destructors going off when an object is freed in C++ also takes a, practically, non-deterministic amount of time. (Really well profiles and controlled programs can make this deterministic if allocation patterns are always identical, but that is rarely the case.)
Of course having fixed sized buffers means you have to have protocols that are aware of size limitations. Most protocols now days assume infinite memory. Everything just fails, badly, when memory does run out.
After having worked in embedded for awhile I grew to deeply appreciate planning around memory limits. Really everyone should be doing it but almost nobody is.
The goose language has dynamic allocation via builtin types, like most systems for the past 40 years (Folks were using dynamic allocation on systems back when 640k was a lot of memory). Most embedded systems these days far exceed the capabilities of 40 year old desk top computers and also use extensive dynamic allocation.
The distinction for goose is that it has fixed locations where the free must occur (function return, effectively), not that it doesn't have dynamic allocation (because it does have dynamic allocation)
People working on cortex m series chips still static alloc though. :D
Them and game programmers. Also the HFT people from my understanding.
The latter two are due to latency concerns.
Still though, it is something that I think more engineers should try out once or twice. Thinking about how buffers actually need to be is a useful exercise.
Yeah, it seems like the sweet-spot for this is real-time and embedded because it should be extremely conservative and consistently fast about memory allocation and de-allocation.
Sad that it's got plug-in stuff as a "non-goal", because I'd love to see this as a scripting engine for gaming (since that's Wouter van Oortmerssen's background). But I imagine a "compiles to C" language would at the very least be functionally impossible to sandbox.
Edit: Question for anybody who's playing with this: When he talks about no generics he says that ADTs still work... is that like his example of writing a function "double" that returns "a + a" and works for any type that supports the plus operator?
It sounds like compile-time duck-typing but I'm having trouble working out the boundaries of that in my head. It sounds like it would only work with fully-open-source libraries for one thing since everything would have to compile from source. Anybody have experience with that sort of thing?
backlands · · focus · HN ↗
So it looks like it restricts the memory management to 100% scope based. I expect that makes a lot of designs for programs not translate to it as well as they fit in Rust or Java (for example). There are a bunch more constraining design choices they list further down:
> - Nothing ever moves
> - ... A string, an array of strings, a record with variable-size fields and an array of those records are each one contiguous block with no pointer in it
I'll have to look a bit deeper to decide if it's feasible to write many things in this language.
bobbydigitales · · focus · HN ↗
tombert · · focus · HN ↗
Say you wanted to make a Node.js framework with callbacks that react to an event. The callback might be a closure that captured some of its surrounding variables. At that point, any of the captured variables are not trivially stack-allocated.
You might be able to do something similar to what Rust does with moving though.
skew-aberration · · focus · HN ↗
cmrx64 · · focus · HN ↗
com2kid · · focus · HN ↗
The tldr is you had to preallocate a struct with anything you wanted captured ahead of time.
jandrewrogers · · focus · HN ↗
thayne · · focus · HN ↗
skew-aberration · · focus · HN ↗
eyegor · · focus · HN ↗
omoikane · · focus · HN ↗
I do that for the Playdate: statically allocate most of the large structures and tables in global variables, and don't call malloc or free after initialization is done.
I also put some things on the stack, not so much because I need to dynamically allocate or free something, often it's because I get lower access latency to the stack compared to main memory (because stack lives inside ARM's tightly coupled memory).
cmrx64 · · focus · HN ↗
skew-aberration · · focus · HN ↗
com2kid · · focus · HN ↗
Dynamic memory management is a performance enhancement. It lets you more efficiently utilize memory vs static allocation at the cost of, well, lots of types of bugs.
You can always preallocate MAX_NUM_ELEMENTS * SIZE_OF_OBJECT for all your arrays. If someone tries to send you more objects then you have buffer space for you just reject the request.
Latency sensitive programs already do this, since memory allocation is rarely deterministic (although it can be in .NET and other similar languages). Likewise a bunch of destructors going off when an object is freed in C++ also takes a, practically, non-deterministic amount of time. (Really well profiles and controlled programs can make this deterministic if allocation patterns are always identical, but that is rarely the case.)
Of course having fixed sized buffers means you have to have protocols that are aware of size limitations. Most protocols now days assume infinite memory. Everything just fails, badly, when memory does run out.
After having worked in embedded for awhile I grew to deeply appreciate planning around memory limits. Really everyone should be doing it but almost nobody is.
codys · · focus · HN ↗
The distinction for goose is that it has fixed locations where the free must occur (function return, effectively), not that it doesn't have dynamic allocation (because it does have dynamic allocation)
com2kid · · focus · HN ↗
People working on cortex m series chips still static alloc though. :D
Them and game programmers. Also the HFT people from my understanding.
The latter two are due to latency concerns.
Still though, it is something that I think more engineers should try out once or twice. Thinking about how buffers actually need to be is a useful exercise.
Pxtl · · focus · HN ↗
Sad that it's got plug-in stuff as a "non-goal", because I'd love to see this as a scripting engine for gaming (since that's Wouter van Oortmerssen's background). But I imagine a "compiles to C" language would at the very least be functionally impossible to sandbox.
Edit: Question for anybody who's playing with this: When he talks about no generics he says that ADTs still work... is that like his example of writing a function "double" that returns "a + a" and works for any type that supports the plus operator?
It sounds like compile-time duck-typing but I'm having trouble working out the boundaries of that in my head. It sounds like it would only work with fully-open-source libraries for one thing since everything would have to compile from source. Anybody have experience with that sort of thing?
itemize123 · · focus · HN ↗