Hacker News
6 hours ago by adastra22

I would throw the entire docs out and write it from scratch in your own words. I get that we live in an era where the machine writes most/all of the code, and I can accept that. What I need, to even consider using and extending this project, is some understanding of what part of the design is yours and what part is accident by Claude. I can't get that from reading Claudese.

3 hours ago by assimpleaspossi

>>I get that we live in an era where the machine writes most/all of the code

Only on the Internet is this true, not in real life. I cannot and do not trust any of these things to do a proper job because they have not in any situation succeeded in any job I've given them. And no company I deal with claims otherwise

3 hours ago by hexasquid

That's like me with violins!

5 hours ago by WillAdams

The version of the documentation which I would very much like to see would be a Literate Programming version where all the code is explained from the ground up.

Apparently, this can actually assist the LLM:

https://silly.business/blog/we-should-revisit-literate-progr...

as discussed here previously:

https://news.ycombinator.com/item?id=47300747

3 hours ago by polski-g

Once a week, I tell Antigravity (3.8-flash) to rewrite every code comment and documentation that was changed in the past week. Neither GPT nor Claude can write like a human.

an hour ago by adastra22

Neither can Gemini.

6 hours ago by felixgallo

We as a society have to cut this low effort commenting out. The documentation is perfectly comprehensible. What action would you take differently if a given feature were implemented by Claude, or a human?

5 hours ago by spuz

If you've ever been tasked with coming up to speed on a system mostly documented with AI writing, you'll quickly realise how hard it is to trust anything you are reading. Even if the Claude documentation is 100% accurate, you'll never shake the worry that some crucial fact you founded your understanding on was wrong. It's a fast recipe for psychosis.

That's without even mentioning that AI writing can often state the what but not the why. That human perspective is usually the most valuable knowledge to get across in writing.

6 hours ago by adastra22

As I said in my message, it would determine whether I use the project or not. I need to match it to my use cases, and if I find a match I need to know: is it matching because my use case falls in the domain of what the human collaborator wants from this project, or is my use case a hallucination that will go unsupported?

You cannot tell either from the AI written docs. I'd rather OP gave a rambling post about some problem he has in gamedev that led him to think a new language was needed, why the constraints are different, and how this will improve X, Y, or Z in his own words. Then I can infer what this project is and where it is going. Right now, I have no clue.

16 minutes ago by harpiaharpyja

It was not well documented. The significance of using "data stacks that the compiler assigns statically" was NOT clear until I backed out of the page and started reading the HN comments here.

5 hours ago by condwanaland

Why are low effort comments not worthwhile but low effort docs are fine?

8 hours ago by koolba

What does this mean (from your link):

> Nested data stays inline. 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. A record that is 160 bytes and an allocation in C++ is 29 bytes and none in Goose.

I’m having trouble parsing that last sentence.

8 hours ago by Aardappel

It means that to do variable sized things like vectors and strings, C++ often ends up having to allocate their contents dynamically. Which results in data structures with lots of 64-bit pointers over multiple allocations.

Even Rust's "enum" feature, which can store different sized things all in the same space, does that at the cost of the smallest variant being just as big as the biggest.

Goose can do all of that not only inline (no pointers), but with variable size, meaning small items take less space. It's like a serialized data representation, but iterable. It makes for big space savings vs these languages.

8 hours ago by eslaught

As far as I can tell, you're essentially creating a new stack for every dynamically-sized variable (because otherwise nothing would be able to grow by bump allocation without moving). But this means you're creating a separate virtual memory allocation for each of these objects, which (I presume?) then rounds the size up to the OS's minimum page size (4KiB or similar).

Doesn't that waste a lot of space? Or is there something I'm missing?

Also it would seem to force every allocation to go through the OS kernel to allocate unless there's some trick to avoid that.

8 hours ago by koolba

These AI generated docs would make more sense if you instruct it to not include numbers unless they form a complete example.

4 hours ago by randfur

I wish it was more clear about the memory layout of nested variable sized data structures. As far as I can work out the max capacity is decided at construction time which makes the whole thing a lot less intriguing.

8 hours ago by lynndotpy

I parsed it as "A record that is ((160 bytes and an allocation) in C++) is ((29 bytes and none) in Goose)."

So, I read it as, "C++ uses 160 bytes and an allocation, when Goose requires 29 bytes and no allocation".

2 hours ago by ashkankiani

I have my own language I'm working on in private and it's nice to see other people coming to the same conclusion on region based memory. I was heavily influenced 7 years ago from learning from HandmadeHero and the community around it, and so I made that memory model one of my goals from the start, and it is indeed possible to get very fast programming with it when you make it your default, and when you make the language able to statically analyze it more.

That is about where our similarities end, though, since I'm doing quite a lot of other stuff in the midst as well (much heavier type stuff, fully incremental, retargetable, reflection, integer range tracking, blah blah blah), and the more goals you have, the complexity blows up exponentially. I do think that the region based memory part alone is worthwhile to have as a language feature, so I applaud your pragmatism. I like your syntax for returning through call stacks, too.

There are other languages that do this, though. Did you look into any of the others? Or ones like Odin which give you the configurable bump allocators and scratch space as well? Mainly I'm curious about your opinions of prior art.

an hour ago by Zecc

I will take a better look at Goose some time later when it's not late at night. Just wanted to drop by and thank you for creating Treesheets. I haven't given its more advanced features the use they deserve, but I love it as a note-taking application for anything that complexity-wise sits between a short outline in a plain text file and a ton of Markdown in something more advanced like Obsidian. And for, of course, any tabular data.

30 minutes ago by baud9600

Great work on Goose, a while load of practical thought went into it.

I’d love to see 1st class lightweight ā€˜processes’ and typed comms like CSP. These light processes would be cheap to spawn in thousands, with synchronous comms. So it’s possible to quickly use arbitrary networks rather than OS thread worker pools with queues. Maybe like:

fn producer(out: chan<i32>) { for i in 10 { send(out, i); } }

fn consumer(inp: chan<i32>) { for i in 10 { print(recv(inp)); } }

fn main() { let c = chan<i32>();

    par {
        producer(c);
        consumer(c);
    }
}
8 hours ago by malisper

I'm curious, for someone more familiar with Goose: how do you represent an arbitrary number of dynamically sized values? If you have a fixed number of stacks, it seems like only a fixed number of values can change size at any given time.

For instance, how would you represent a hash table where the values are strings and at random, the program inserts or deletes a random string?

This doesn't seem like something you could easily represent. The only way I can think of is to keep a stack that holds all of your strings, and you periodically compact it.

Edit: Maybe you could also have a separate stack for strings of various sizes. One each for strings less than 8, 16, ... bytes. But at that point you're basically implementing your own malloc by hand.

Edit: Fwiw I do think Goose is very cool! I've had to hand-roll a lot of similar stuff in Rust before to speed up memory management

7 hours ago by Aardappel

Certainly, this is a language where you get the most benefits if you are able to structure your data usage such that things of similar lifetimes sit together in arrays.

For example, you can build up a tree of all variable sized nodes inside a single array.

Where it gets interesting is if you must arbitrarily delete tree nodes, and you can't structure it to do that in stack order. The language has various tools for this, like fixed arrays with capacity, or pools of either single elements or runs of elements.

8 hours ago by progval

I'm not familiar with Goose, but I'm guessing you could define a single stack and put your dynamically sized values in it. Essentially rewriting a memory allocator on top of Goose's stacks. This is what they seem to be doing here: https://github.com/aardappel/goose/blob/master/samples/13_li...

8 hours ago by malisper

Yeah, that looks like a freelist approach. That will work as long as the values you're allocating are all fixed-size. You'll need something much more complicated if you want arbitrarily sized values

That example implements a linked list of integers. I'm curious how you would do a linked list of strings

8 hours ago by andsoitis

> how would you represent a hash table where the values are strings and at random, the program inserts or deletes a random string?

Goose has a built-in generic hash table called dictionary<K, V>, provided by its standard library.

https://aardappel.github.io/goose/docs/stdlib.html#dictionar...

8 hours ago by malisper

From the link

> Keys and values are fixed-size

so not quite what I'm looking for

8 hours ago by andsoitis

You can store the strings separately and have the dictionary hold references to them.

Conceptually:

dictionary<i64, StringReference>

             |

             +----> "hello"

             +----> "a much longer string"

             +----> "x"
8 hours ago by James_K

I think the limit of this would be creating your own allocator that works with the stacks, but you could probably stop short of that in most cases.

It's not entirely mad to do it this way, and I can see some benefits. For one, you might have multiple of these pools across the program for different data-types, which would make allocating to any one of them a cheaper operation. It is much more reference safe since you are only ever freeing stuff in a certain context and you can still never have dangling pointers. When you look at memory safe languages, they all default to this eventually. Like Rust in the advanced case will have you implementing your own allocator, lot's of games use this thing called ECS which is essentially a kind of allocator. Goose would just have it be more common.

8 hours ago by malisper

This is roughly what I do in Rust. I use different static types for values based on how long they'll live. Temporary values get one type; cached values get another. The allocator allocates each value in a different location based on how long the value will live.

9 hours ago by bobbydigitales

"That looks really neat! The automatic analysis and use of multiple data stacks and resizable fields takes it from "lots of work can be done this way" to "basically everything can be".

The relative references and built in binary structure validation also enable direct memory mapping of data structures and immediate use of network data. "Parsing" file and network data is often 100x slower than it needs to be." - John Carmack

7 hours ago by pradn

Goose is pretty cool. The idea is that you don’t need to make representable all programs: a language for a restricted purpose is ok. As long as you can statically specify the number of growable memory regions, you can use Goose. However, since there’s no garbage collection, you’ll probably need to be careful about memory use while a program is running. Ie: the stacks can get too big if you keep growing them, even as old data is not used any more.

Still, for a large number of programs - like data-oriented applications - it’s probably a good fit. It might work ok with entity-component game systems as long as you reuse old memory…

7 hours ago by Aardappel

You typically "allocate only" if a data structure is made entirely on construction, or if its growth is bounded.

If it is potentially completely unbounded, you need different solutions like a pool, or essentially reconstructing etc.

8 hours ago by ebiederm

I seem to remember the ML guys went down this route. I believe they called it regions.

From what little I read in the literature I seem to recall that there were enough programs with quite a bit more memory usage that they decided this approach was a dead end.

Does anyone know anymore details?

8 hours ago by Aardappel

Yes, ML Kit region inference is probably the closest prior art to Goose.

Back then though, they couldn't lean on large 64-bit address spaces like Goose can. They implemented all of this with a chain of blocks of memory instead, and tracked most of it at runtime that Goose now does at compile time.

https://github.com/aardappel/goose/blob/master/docs/design/p...

8 hours ago by anigbrowl

This looks very interesting! I mostly write in garbage-collected languages (to the extent that I still write anything by hand...) so I'm just a spectator in memory management debates, but it's often struck me that heap management is more of an art than a science. The idea of treating memory more like stacks made immediate intuitive sense to me. I'm also fascinated by the thread implementation, although I'm not knowledgeable enough to to think through the potential benefits/costs vs other approaches to concurrency.

I wonder if the name of the language was inspired by the way geese fly in formation, with trailing birds saving energy by flying inside the aerodynamic shadow of the leaders, and swapping in and out as needed. If so, a very nice metaphor for the memory management model.

I was also impressed by the documentation. As we know AI-generted docs tends to be rather mediocre, but the author has clearly invested time in making in readable such that the relevance and rationale of design decisions provide the context that a curious programmer needs to understand why things are implemented in a particular way.

I really appreciated the detailed samples, ranging from simple algorithmic theorems up to a small game. Again, I don't have the experience to rate the language vs others, but I was struck by readable the code was and how easy it was to follow task flow. Not having to think about classes is always a plus!

Anyway, I usually the the offering of a new language with dispassionate interest, as something to be aware of and but not get too invested in or familiar with until it gains enough popularity to have a good shot at longevity. Goose is the first language in a long time where I looked at it and immediately thought that I'd like to use it for its own sake.

7 hours ago by Aardappel

Thanks!

The name is an animal because all my past PL designs are animals (I also made Lobster etc). Goose seemed like a fun name.

6 hours ago by malkia

"Threads that share nothing. A worker is compiled as a separate program with its own memory, and flat values cross typed queues as a memcpy. Data races, locks, atomics and memory orderings do not exist in the language."

That reminds me of Dart Isolates - https://dart.dev/language/isolates

Daily Digest

Get a daily email with the the top stories from Hacker News. No spam, unsubscribe at any time.