Hacker Newsnew | past | comments | ask | show | jobs | submit | xen0's commentslogin

Reading through, something small caught me by surprise.

https://c3-lang.org/language-common/arrays/#fixed-size-multi...

Multi dimensional arrays are not declared in the same way they are accessed; the order of dimensions is reversed.

Accessing the multi-dimensional fixed array has inverted array index order to when the array was declared.

That is, the last element of 'int[3][10] x = {...}' is accessed with 'x[9][2]'.

This seems bizarre to me. What am I missing? Are there other languages that do this?


Please consider a variable `List{int}[3] x`, this is an array of 3 List{int} containing List{int}. If we do `x[1]` we will get an element of List{int}, from the middle element in the array. If we then further index this with [5], like `x[1][5]` we will get the 5th element of that list.

If we look at `int*`, the dereference will peel off the `*` resulting in `int`.

So, the way C3 types are declared is the most inside one is to the left, the outermost to the right. Indexing or dereferencing will peel off the rightmost part.

C uses a different way to do this, we place `*` and `[]` not on the type but on the variable, in the order it must be unpacked. So given `int (*foo) x[4]` we first dereference it (from inside) int[4], then index from the right.

If we wanted to extract a standalone type from this, we'd have `int(*)[4]` for a pointer to an array of 4 integers. For "left is innermost", the declaration would instead be `int[4]*`. If left-is-innermost we can easily describe a pointer to an array of int pointers (which happens in C3 since arrays don't implicitly decay) int*[4]*. In C that be "int*(*)[4]", which is generally regarded as less easy to read, not the least because you need to think of which of * or [] has priority.

That said, I do think that C has a really nice ordering to subscripts, but it was unfortunately not possible to retain it.


Thanks for pointing out what I was missing.

Please consider a variable `List{int}[3] x`, this is an array of 3 List{int} containing List{int}. If we do `x[1]` we will get an element of List{int}, from the middle element in the array. If we then further index this with [5], like `x[1][5]` we will get the 5th element of that list.

I get that motivation. In C++ it's an odd case that where `std::vector<int> x[4]` is "reversed" in a sense compared to `int x[4][100]`. And this quirk is shared with other languages (Java, C#).

But in my experience, mixing generic datatypes like this with arrays is quite rare, and multi-dimensional array like structures with these types is often specified via nesting (`std::vector<std::vector>>`) which avoids confusion.

The argument re. pointers is more convincing though.


File it with the footgun of the two different array slicing syntaxes: https://c3-lang.org/language-common/arrays/#slicing-arrays

I have already opened a discussion about this with the author, and I must say I agree to disagree that a language needs arr[start..end] (inclusive) as well as arr[start:len] (up to len-1) and if you use the wrong one, you’ve now lost a foot and your memory is corrupted.


The closed intervals for slices caught my eye as well, but I simply filed that under 'that's a weird quirk' rather than 'wtf?'.

It would require more thinking on my end to change that to either 'this is an acceptable choice' or 'this is a terrible idea'.

But the array indices being reversed on declaration? I cannot think of an upside to that at all.


Looking at those in my extended family that have reached retirement, this does not appear to be a given.

End of life care* is highly variable in duration and costs and many people do not adequately prepare for expensive endings.

* this is true of more than just care post retirement


Plus most of what needs to be done is highly informal and unstructured. Money can only buy so much. It can't buy someone who is going to actually represent your interests, rather than charging gobs of money for the illusion.


An unfortunate reality is that you're never going to have such services until there are children for them to service.

Decline like this is difficult to reverse, but that doesn't mean we shouldn't try.


I doubt it would make much of a difference. Children growing up in rural communities typically move to a bigger city as soon as they can, which is where they then find mates and start their own families. I suspect not many young people are going to give up the social opportunities to stay in a small town or move back there.


But when they want the family, they have the option to go someplace to build it. That's the point. Right now the people meet in the city and stay in the city because they're tethered there.


Your real commit history is irrelevant. I don't care too much about how you came to a particular state.

The overall project history though, the clarity of changes made, and that bisecting reliably works are important to me.

Or another way; the important unit is whatever your unit of code review is. If you're not reviewing and checking individual commits, they're just noise in the history; the commit messages are not clear and I cannot reliably bisect on them (since nobody is checking that things build).


It's sometimes nice to be deterministic.

I don't often care about a specific order, only that I get the same order every time.


Thinking about this upfront for me, I am actually wondering why this is useful outside of equality comparisons.

Granted, I live and work in TypeScript, where I can't `===` two objects but I could see this deterministic behavior making it easier for a language to compare two objects, especially if equality comparison is dependent on a generated hash.

The other is guaranteed iteration order, if you are reliant on the index-contents relationship of an iterable, but we're talking about Dicts which are keyed, but extending this idea to List, I see this usefulness in some scenarios.

Beyond that, I'm not sure it matters, but I also realize I could simply not have enough imagination at the moment to think of other benefits


I work on a build system (Bazel), so perhaps I care more than most.

But maybe it does all just come down to equality comparisons. Just not always within your own code.


Being able to parse something into a dict and then serialise it back to the same thing is a bit easier. Not a huge advantage, though.


Open source projects? Maybe less so.

But there are definitely companies that use Bazel in a major way.


At least in British English usage, there is no distinction between Jail, Gaol, and Prison other than at least one of these is a dated word.

I believe only the US has a strong distinction between Prison and Jail.


Part 4c (this is quite a long series) goes into some detail here. https://acoup.blog/2025/09/12/collections-life-work-death-an...

My own interpretation is that it's difficult to precisely compare how peasants were exploited to modern taxation regimes in the developed world. Perhaps more as an unfavorable relationship with the only employer in town?


This may be because the 'headshot' multiplier is lower than the regular multiplier (1x vs 2x) for the prod and baton. For most weapons the headshot multiplier is 8x (or something).

So torso hits from behind are the way to go.


Those are not the same; one is a bit less than an hour, another is 3 and a half days.

A microcentury is 100 nanoyears if you prefer that.


It's actually 100 microyears!


Erm, yes. Yes it is...


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

Search: