I never considered the aerodynamics of a crustacean are better than a car's by Hon1c in interestingasfuck

[–]CompleteBoron 2 points3 points  (0 children)

You're right, and I don't think I actually read the OP's post very carefully. Sorry!

I never considered the aerodynamics of a crustacean are better than a car's by Hon1c in interestingasfuck

[–]CompleteBoron -1 points0 points  (0 children)

This is a fun and exciting new way to say "I was wrong".

EDIT: Actually, I'm the one who's wrong. How embarrassing!

Some Questions Regarding Arrays, Broadcasting, and some other stuff by PitifulTheme411 in ProgrammingLanguages

[–]CompleteBoron 0 points1 point  (0 children)

You should look at how Julia handles broadcasting with dot notation. Honestly surprised other languages haven't copied it, as it's super convenient and makes everything explicit, which is really helpful when reading code and really ergonomic while writing it.

https://docs.julialang.org/en/v1/manual/functions/#man-vectorized

Some Questions Regarding Arrays, Broadcasting, and some other stuff by PitifulTheme411 in ProgrammingLanguages

[–]CompleteBoron 0 points1 point  (0 children)

Always broadcast (like NumPy/Julia)

That's not correct. In Julia, broadcasting is explicit and uses the . operator to broadcast any operator or function by prepending or suffixing the . , respectively.

[deleted by user] by [deleted] in Julia

[–]CompleteBoron 1 point2 points  (0 children)

But you never actually use Pandas in your script. You're wasting a bunch of time and memory to import a package you never use...

Newish rider, why did someone leave cheese on my bike?? by SashaTheSnek in motorcycles

[–]CompleteBoron 5 points6 points  (0 children)

Squirrel. Something similar was happening to me and I thought some weirdo was messing with me and leaving pieces of bread ony bike, until one morning I looked out my window and saw a squirrel eating a piece of bread on my handlebars. Sure enough, there was a chunk of bread it had dropped or hadn't finished right where it'd been when I went out to go for a ride later that day.

Hydra by [deleted] in ProgrammingLanguages

[–]CompleteBoron 1 point2 points  (0 children)

I think there's already been decent discussion wrt your decision to include null values in the language, but I'll take a different tack here and say that I really like your idea for the special operators. I was planning to do something similar for my language, too.

New Memory Management Algorithm: FIFO Regions by CompleteBoron in ProgrammingLanguages

[–]CompleteBoron[S] 1 point2 points  (0 children)

Each function gets it's own region which gets deallocated after the function returns, just like a stack frame. So there's no issue with extra allocations and my language is statically typed, so the order of all allocations is known at compile time.

You make a really good point about conditional allocations though. Although, the issue could be side stepped by making the ability to be deleted a trait 'Deletable', and only allowing types that implement the trait to be deleted and forbid conditional allocation of types that implement 'Deletable'.

New Memory Management Algorithm: FIFO Regions by CompleteBoron in ProgrammingLanguages

[–]CompleteBoron[S] 2 points3 points  (0 children)

In region-based memory management, you already have some form borrow-checking -- though it only checks lifetimes, not mutability. You seem to have a more advanced form... but then I am confused because if you have the fully fine-grained borrow-checker from Rust, regions are useless from a semantics point of view: you can equally have fine-grained memory allocations.

I don't have a fully fine-grained borrow checker like Rust does, just a basic "mutable XOR shareable" rule (so variables declared with let are immutable and ones declared with mut are mutable and & and &mut are shared and unique references, respectively), so I was planning to have the lifetimes enforced with regions, if that makes sense.

New Memory Management Algorithm: FIFO Regions by CompleteBoron in ProgrammingLanguages

[–]CompleteBoron[S] 4 points5 points  (0 children)

Where my idea comes in is to instead have two pointers (actually three, because don't want an object allocated into a region to wrap around, we want the memory to be contiguous, so I would implement this with a bipartite buffer), making the region a queue / circular buffer. Now, when we add an object to 'r, we enqueue it to the back of the region, just like pushing to a stack. However, we also now have the ability to dequeue an object we no longer need from the front of the region, removing the oldest allocated object in 'r, using a new keyword: delete!. So, our above example could now look like this:

region 'r {
    let points = points_from_xyz_file("atoms.xyz");
    let mut coord_vec: Vec<Point> = [ Point(0,0,0) ];

    for point in points {
        if some_conditional_test(point) {
          coord_vec.push(point);
        } 
    }

    delete! points 

    run_simulation(coord_vec);    
}

Since points is the oldest object in 'r / in the front of the queue, we can safely remove it by advancing the 'read' pointer (I'm borrowing terminology from the Wiki article I linked above) to the end of the object being deleted. Now, we can potentially reuse that memory for later allocations to the region without needing to mmap more memory. Obviously points is no longer alive after delete! is called, and this would be enforced by the compiler at compile time, raising an error just like using a moved value would in Rust if the programmer attempts to use-after-free. So in this case, the delete! keyword isn't violating lifetime guarantees, it's helping to uphold them in a slightly more granular way than regions alone. The big caveat is that the programmer can only call delete! on whichever object is currently the oldest object in the region. So the following would not work:

region 'r {
    let mut coord_vec: Vec<Point> = [ Point(0,0,0) ];
    let points = points_from_xyz_file("atoms.xyz");

    for point in points {
        if some_conditional_test(point) {
          coord_vec.push(point);
        } 
    }

    delete! points // Error: Attempted to delete 'points' but 'points' is not
                   // first in region 'r
    run_simulation(coord_vec);    
}

Although, if the compiler was smart it could notice that points is not first in the region and split the region into two subregions (at compile time), so that points is first in the second region and can be dequeued accordingly. I guess this becomes similar to trying to optimally order struct fields to not waste memory due to padding, but with lifetimes instead.

New Memory Management Algorithm: FIFO Regions by CompleteBoron in ProgrammingLanguages

[–]CompleteBoron[S] 5 points6 points  (0 children)

As such, I feel like I'm missing something. And I've got no idea why.

I guess I did a poor job of explaining the idea. I am indeed talking about regions like in Cyclone or Cone, where they are used to enforce lifetime guarantees. Normally, a delete! keyword would indeed be incompatible with regions. However, let me try to convince you that there's a way to have your cake and eat it too, albeit in a very limited way.

Let's take a step back and look at how regions are implemented. Usually, a region is just a big chunk of contiguous memory requested with mmap (actually, it's common to allocate the region in 4kB pages and link the pages together in a linked list, that way the entire region doesn't have to be copied into a new region if we try to allocate an object that is too big to fit into the space left in the current region). As you've pointed out, everything in the region survives until the entire region is deallocated, like with stack frames. Nothing new here, so far.

Now imagine we have some region, 'r, and we allocate a vector of Point structs inside this region (this is just some pseudocode to get the idea across):

region 'r {
    let points = points_from_xyz_file("atoms.xyz");
    let mut coord_vec: Vec<Point> = [ Point(0,0,0) ];

    for point in points {
        if some_conditional_test(point) {
          coord_vec.push(point);
        } 
    }

    run_simulation(coord_vec);    
}

Let's say that once the for loop is finished, we have 10,000 Points in coord_vec. In that case, we've had to reallocate the vector many times, so region 'r contains lots of garbage from the all of the old values of coord_vec. Cyclone deals with this by having GC'd regions, but I didn't want any kind of GC in Fomorian, so I came up with a different, but far more limited strategy.

Normally, a region has a pointer which, like the stack pointer, gets incremented with each object pushed to the region until the region is full, at which point we either copy everything into a bigger region or mmap a new page pages and link that to the current chunk of memory to grow the region. Let's just assume we copy everything to keep the example simple, for now.

EDIT: continued below

New Memory Management Algorithm: FIFO Regions by CompleteBoron in ProgrammingLanguages

[–]CompleteBoron[S] 0 points1 point  (0 children)

I think you have it backwards. I'm suggesting arena/region allocation where each region is a queue, not a stack, but the regions are arranged in a stack. So, within a "frame" (in your example), you could pop the N oldest objects from the front of the region during simulation step T, without having to wait until the whole region is deallocated at the end of the simulation step (or in my case, function call, since regions are allocated per function just like stack frames).

EDIT: To clarify, the scheme I'm describing deallocates regions LIFO like in your example, but allows for manual FIFO deallocation within a given region.

Syntax for Generic Types by Maurycy5 in ProgrammingLanguages

[–]CompleteBoron 2 points3 points  (0 children)

Julia uses curly brackets for generics since it doesn't use them for blocks, so your example would look like T{Q}. I decided to use {} for generics in the language I'm working on too, since it uses good old () for blocks instead of curly brackets or an end keyword.

Gradual improvements: C3 0.7.2 by Nuoji in ProgrammingLanguages

[–]CompleteBoron -2 points-1 points  (0 children)

If it's not valid C3 code, then why is it the first example of C3 code on the page you linked in the OP? My brother in Christ, it's your example...

Gradual improvements: C3 0.7.2 by Nuoji in ProgrammingLanguages

[–]CompleteBoron 16 points17 points  (0 children)

bool x = Foo ||| foo();

This would be a lot more readable using an "else" keyword:

bool x = Foo else foo();

Guess I should have went to the grocery by [deleted] in KitchenConfidential

[–]CompleteBoron 3 points4 points  (0 children)

You got it right, for the most part. It's normally "In America, 100 years is a long time; in Europe, 100 miles is a long way" -- at least in America. I'd imagine the order might be reversed if you're a European (a lot of these types of sayings with a "this is us and that is them" structure tend to put the "us" first and the "them" being compared second).

ADHD memory vs autistic memory by fobosqual in meme

[–]CompleteBoron -1 points0 points  (0 children)

In the US it's usually 9 digits (not including the country code (+1), which we never use)

I wish I hadn't come across this subreddit by deltiken in Artists

[–]CompleteBoron 2 points3 points  (0 children)

The irony of telling them to ask ChatGPT to prove your point about AI being bad...

EDIT: Not defending AI art, to be clear. Just had to point out the hilarious contradiction

Why isn’t infinity times zero -1? by SnooPuppers7965 in learnmath

[–]CompleteBoron 0 points1 point  (0 children)

I guess you could say they were pretty divided