In C a pointer can point to any arbitrary offset within an object or array, to a local variable somewhere on the stack, to a static variable, to read-only memory, to the first(?) of an indeterminate number of characters (hopefully) terminated by ((char)0). To the first of a statically unknown number of variables located somewhere in memory, to a variable of indeterminate type (thanks to union), to I/O devices, and also to unallocated memory since there's no bounds checking.
A reference can only point to an object or an array on the heap. Array indexing is bounds-checked.
It seems obvious to me that these restrictions make references easier to reason about than C-style pointers, and therefore easier to learn.
>It seems obvious to me that these restrictions make references easier to reason about than C-style pointers, and therefore easier to learn.
I came to C from Assembly, so maybe I'm in a different camp, but references seem to me to be more difficult to reason about than pointers. Pointers just are, like math; references seem like a bunch of semi-arbitrary conventions.
Like the difference between writing SQL and using an ORM, which is supposed to be simpler but ends up being messier.
I imagine most of these examples (besides strings) isn't something you learn in the beginning and when e.g. doing operations on linked lists you're pointing to either allocated structs or null.
You tend to learn it early not by choice, but because the student makes some operation on the pointer and suddenly all they get are core dumps or (seemingly) bizarrely corrupted data and they have to confront what's going on early in the learning process.
«Why dont O/S support executables with something like LLVM binaries and generate the native code at load time ?»
I've wondered this too. I can think of two systems "IBM i" (formerly OS/400) [1] and Oberon "Slim Binaries" [2] off the top of my head. I suspect that the answer to your question is some mix of path dependence and engineering trade-offs.
For example, if the system has unix-style paged virtual memory (which Oberon did not), it's probably convenient to be able to directly map pages of native instructions into memory without needing to translate or massage them first.
In the case of "IBM i", which I've only ever read about, it sounds like it moves complexity from e.g. the compiler into the loader and so closer to the Kernel of the operating system. If I wanted to better understand the net cost/benefit analysis of this design I'd look for more detail on work done to port to PowerPC.
One would assume that, but in practice, the predominant style is not one of many short procedures. Instead it feels that there's a preference to just inline the code unless the resulting procedure will have more than one caller.
Control structures are deeply nested and this goes on for 64 (very dense) lines. The low line count but is an artifact of how Oberon is conventionally formatted. When reformatted to mimic the conventions of languages like C, Java or Python it works out to more than 120 lines.
When I program in Oberon (recreationally) I tend to follow this style even though I would extract the same code into a separate method were I writing in Java.
For extra fun consider the German-Speaking word where CSV files are actually Semicolon-Separated but everyone still calls them CSV and looks at you like you drooled on yourself when you point out that “;” is not a “,”.
This appears to be because we use “,” as decimal separator and were too dense to learn how to use " properly in CSV.
The early days of manual typewriters, paper tape, teletypes and vacuum tube systems, which already followed this practice predate US-ASCII, so I don't think the particular numeric values assigned by US-ASCII can have any explanatory power in answering this question.
Me, I blame the Romans ;-)
The Latin alphabet was initially only what we call the "upper case". What became the lower case came (a millennium?) later, first as an alternate style of handwriting and then as an addition to the alphabet along with rules about when which form of each letter should be used.
Given the need to economize as in 5-bit teletype codes it's not surprising the chosen convention was to print (or later display) those codes as upper case as that is, historically speaking, the default.
Still, I like to wonder if anyone every thought to build a teletype that printed in lowercase just to screw with people. :-D
The teletypes needed all the control characters as well (cr, lf, bell, etc.), so everything below ASCII 97 was mostly required.
If I remember correctly, Apple terminal emulators set reverse video when they meant a capital letter, so you could converse with something over a modem that was sending lowercase.
When I wrote "teletype" I wasn't referring to what teletypes had become by the time by the time Unix was developed. Think further back than that. This is why I mentioned 5-bit codes:
This coding scheme is so constrained (32 possible 5-bit values) that it uses the codes FIGURES (01000) and LETTERS (10000) to toggle back and forth between two alternate sets of meanings for the remaining 30 possible codes. Still not enough space for lower case or ASCII's plethora of control codes (just NUL and DEL).
I've always suspected that 'Reader' and 'Writer' were names borrowed from Oberon since that's one of the influences that contributed to early Go design:
Enumerations and subranges (in style of Modula-2 and Pascal) are missing from Oberon, but Records are present subject to type extension in the style of structs in Go.
In Oberon(-1), we used (pointers to) procedures in record fields as methods when programming in an object-oriented style.
Oberon-2 added methods which dispatch dynamically based on type of receiver. These were "type bound procedures". You'll find this idea echoed in Go as well.
I was shocked by how spammy Amazon.com's search results seemed compared to what I'm accustomed to from Amazon.de. I'm not a regular user of Amazon.com but have had occasion to do so since I'm visiting family in the US. Amazon.de is the "local" Amazon where I live.
Is this an affect of differing laws in the EU versus the USA? Differences in leadership of Amazon.com versus Amazon.de? Differences in perceived market expectations? Perhaps the average American consumer is expected to be more tolerant of this kind of thing? (I wonder because I compare the robo-call-infested hellscape that we've made of our telephone system compared to the rarity of such abuse where I live in Europe and wonder if we, in the US, are just more prone to behave in a way that produces tragedies of the commons.)
A reference can only point to an object or an array on the heap. Array indexing is bounds-checked.
It seems obvious to me that these restrictions make references easier to reason about than C-style pointers, and therefore easier to learn.