Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Are there actually programmers who need to be explained the following: "...memory is just a series of numbered cells, and variables are just nicknames for a memory location assigned by the compiler."

What kind of programming can one do without even that level of mental model of what a computer does?



Most (keyword: Most) self-taught programmers / hobbyists start with high level languages like Python, Ruby, PHP, JS etc and work their way "down" out of interest and intellectual stimulation (like myself). It might be counter-intuitive to those with CS backgrounds but the truth is for most things, you don't really need to know the implementation details of variable assignement if you're only interested in scraping the NYT.

Believe or not, pointers can be difficult to grasp as a concept for people who aren't used to this type of mental model.

If you didn't struggle with it, good for you. But there's no need to look down on others who are trying to learn. I should also add that Software Engineering and Programming aren't necessarly synonyms. Some programmers aren't SWE and that's OK.

If you're a "fake programmer" like the parent is trying to imply, don't lose hope. Continue to learn at your own pace and you'll eventually catch up.


> If you're a "fake programmer" like the parent is trying to imply...

You probably shouldn't put words in other people's mouth.

I don't think he was calling the people fake, but merely asking how effective they could be at programming without an understanding of memory.


I admit it was a bit harsh but the parent comment sounded a bit too condescending.


I can see that pointers are conceptually difficult (the passage I quoted was not about pointers). I'm not even looking down on anyone. I'm just honestly surprised that programmers might not know what RAM is.


Just people who are new to it mostly, this must be aimed at people who haven't done any low level development at all. Some people seriously struggle with it though, I don't think I had a truly full grasp until I started reverse engineering and saw the memory first hand and how it was accessed with different instructions.


Actually you don't need to know about numbered memory cells for most modern languages that aren't C, C++, or assembly.

It's a good thing. Most of the time for most of the people, it's better to work closer to your problem domain than to the CPU.


> It's a good thing. Most of the time for most of the people, it's better to work closer to your problem

Having a rough understanding of what memory is at a very rough high-level grasp ("numbered byte-size cells" isn't very in-depth after all) doesn't preclude one from working "closer to one's problem domain", likewise lacking such grasp doesn't bring one any closer to one's problem domain.. what am I missing?


It's not that such an understanding precludes a person from working close to the problem domain, it's just that that knowledge is not necessary most of the time.

In the book, "Mythical Man Month", Fred Brooks talks about the two kinds of complexity in solving problems with computers. There's the "essential complexity" that's there because the problem you are solving is actually complex, and then there's the "accidental complexity" that's not actually required to solve the problem, but to make the computer happy.

Let's compare C arrays and Python/C# Lists. For my pretend problem, I need an ordered, index-able set of things.

With the C array, I need to know how big to make it before I create it. I need to allocate the memory that is used before I use it, and I must deallocate that memory when I'm done with it. I might underflow or overflow the array and allow Eastern European hackers control over my server and data. Even if I checking for overflows and underflows in all the proper places, I also have to add code to every one of those places handle each possible error.

Whereas in C# and Python, I just make a new list and stick things into it. When it goes out of scope, it disappears automatically.

Python and C# move me closer to the actual problem being solved by removing this "Accidental Complexity". When complexity removing is done well, it also removes the requirement for the programmer to know about numbered cells of memory, because numbered cells of memory is "Accidental Complexity" for the problem domain.

Now when I know how the computer is actually working, it does bring benefits. Today, in fact, I'm writing C code for an embedded ARM chip. Knowledge of memory numbers is a little required here. But for most software developers, knowing how memory works is not a requirement for working software. Even memory-as-a-numbered-set-of-cells is still just a huge abstraction from how the memory is actually being handled by the hardware.


> With the C array, I need to know how big to make it before I create it ..

But that is essential complexity when you need to reason carefully about memory use.


The parent just said that it's a good thing that these languages don't require an understanding of memory, not that such an understanding is not valuable.

If you need to understand memory to use a language, then it's not abstracting well enough.


Yeah, that's why we have chat programs taking 5-10% of the CPU when idle and in the background. The developers worked "closer to the problem domain".


Is it their fault that we still haven't been able to find an elegant solution to this problem?


There are many elegant solutions; they're not JavaScript on Electron.


> What kind of programming can one do without even that level of mental model of what a computer does?

JavaScript? Python?


I'm pretty sure to program in Javascript you need to understand that primitives are passed as values, while objects are essentially passed by pointers, and if you modify one inside the callee, the caller will see the modifications.

Understanding this fact does not strictly imply having a basic understanding of memory, but it gets pretty close to it. I would personally be weary of some who calls itself a programmer or software engineer and couldn't write this article themselves.


Primitives being passed by pointer or value....what is the difference?

The only relevant parts is that (1) they are immutable and (2) they are compared by value.


There is an argument to be made that is true for any of the top 10 programming languages with the exception of perhaps C and C++.


Surely you need to have some kind of idea of what memory is just to write:

  var a = 1
  var b = 2
You have to know that these values are stored in working memory, not on hard drive or Google's servers or Martian stone tablets.


No? All you need to understand to program are the assignment semantics.

Understanding the implementation details is valuable, but I'm not sure why you think it's necessary to program?


I just don't see what kind of useful programming you can do without knowing anything about the machine it runs on.

If "a = b + c" takes a second to execute, you have to take that into account. The programs that people wrote for 1950s computers were very different from today, even though the language semantics might be essentially the same.

On the other hand, this discussion is helping me understand why the web development world is full of weird database-backed Rube Goldberg machines that can spend milliseconds to access a few bytes of data that were already in RAM.


>If "a = b + c" takes a second to execute, you have to take that into account.

But it doesn't, so you don't.

Sure understanding performance is necessary to build more complex or higher usage systems, but not understanding it does not preclude "useful programming".


>If "a = b + c" takes a second to execute, you have to take that into account.

But it doesn't, so you don't.

How do you know it doesn't? What if assigning to 'a' writes to a remote database and waits for the write to be confirmed?

More to the point, how does a new programmer know that is not the case? The average person's expectation of computation speed is shaped by the experience of using server-side web apps: you click on a button, a new page is loaded from the server taking multiple seconds to finish.

To understand that an assignment doesn't run that slow, you need to be told that. Surely explaining local memory would be part of that.


To understand that an assignment doesn't run that slow, you need to be told that.

Not really. You just try it, and notice it ran instantly. You don't really have to care how it happens to run behind the scenes, as long as you have a working model of the semantics. That's the entire point of most abstractions, to make it so that you don't have to think about all the details when you don't want/need to.


Did you never go through the beginning phase where you didn't understand pointers? That's usually a breakthrough moment, not something you start out with.


No, because the languages I had available to me were Timex 2068 Basic and Z80 Assembly.

Maybe the first couple of hours when I still hadn't read the DIM, DATA, READ, POKE and PEEK manual pages.

Just like on Dave Cheney's post, seeing a few box examples was enough to get it.


So you benefitted from exactly the sort of explanation you now seem to be questioning?


No, because I never had a "breakthrough moment".

It just felt natural on how a computer was working, typing example after example, to a 10 year old version of myself.


There's a certain distinction to be had between understanding memory addresses, and understanding pointers as part of a type system. I remember the former was very straightforward in various BASIC dialects running on DOS, and it never really confused me. C pointer types, on the other hand, did. Sure, there's an obvious mapping between the two... in the retrospect. But it wasn't obvious at first.


Depends where you start from, really. If you come from the "bare metal" side of things (electronic work, microcontrollers etc...) then work your way "up" then the memory model is all you think about. I learned pretty much that way so I never really had much of an issue understanding these concepts (conversely, it took me a while to get used to things like dynamic typing).

That being said nowadays I'm sure many more coders start with something like Javascript instead of 8bit controllers, so I'm sure these types of articles are very valuable to many.


Sure. I'm not questioning the need for pointers to be explained.

I'm just surprised that an explanation geared for programmers would need to also explain that variables are stored in local memory, or what RAM is. (Again, there is nothing wrong with explaining that.)


You can get pretty far without knowing that. A big chunk of Go's audience seems to be Python programmers who want something that isn't quite so slow, and you can probably do a whole career in Python without ever knowing what a pointer is.


I'm so glad I learned how to program on a C=64. Even using Commodore BASIC one was introduced to how memory worked so that one could use PEEK and POKE commands. This made learning C and pointers so much easier because the mental model was there already.


(I upvoted you, I think your question is fine FWTIW)

Sadly, yes. Universities have moved away from teaching C. In ancient times, when I went to school, you'd start with an intro class in Pascal, then you'd take a data structures class in Pascal, and then you'd take some harder class in C.

About half of the people in the C class would drop out of Computer Science when they hit pointers. As someone who gets pointers pretty much instinctively, I didn't get it, the concept seemed really intuitive to me. But apparently that's not true for everyone, some people really struggle with it.

I think it really doesn't help that CS has moved away from C as a teaching language. C can be viewed as a pleasant, portable, assembly language. As such, it lets you "feel" the bare metal, much more so than a scripting language like Python or Javascript.


Oddly I find pointers intuitive and easy in Pascal and assembler - arcane and complicated in C. Java (memory model) is also rather difficult to internalize IMNHO - probably because of the complication of "bare" types (eg: int), boxing, pass by reference and some rather muddy default/usual containers/objects/arrays etc.

Other than for teaching "an industry language" I don't immediately see much reason to teach C and Pascal - but I suppose the "modern" equivalent would be Python, Cython, C and assembler, followed by haskell/(oca)ml, Prolog and/or a lisp/scheme - with the benefit of showing C interop along the way.


I can't help but wonder if the reason why Pascal pointers feel less complicated because they're more constrained, or because of the syntax, or both.

On the constrained part of things, there's no pointer arithmetic, and in Standard Pascal, there's no "address of" operator at all - a pointer can only point at dynamically allocated memory block, not at global or local variable, or some memory location inside another block. Consequently, there's also no pointer arithmetic. This is sufficient to make linked lists and other similar data structures, but also makes the concept much more opaque compared to C (i.e. it's less obvious that it's really a numeric address).

On the syntax part, I think the big problem with C is that the moment you start dealing with pointers, the arcane rules for declarator precedence are in play. Pascal, OTOH, has a very regular type syntax, which in case of pointers is also easier to read - you just read ^ as "pointer to", and so ^integer is "pointer to integer". Same thing for dereferencing - again it's ^, but there you read ^ as "points to", and so a dereference like x^ becomes "what x points to". And there's also no confusion with any other operator, since ^ is reserved for pointers alone, and it has a fairly obvious mnemonic to it.


> Oddly I find pointers intuitive and easy in Pascal and assembler

Sure, sixy seven lines of assembly handily beats arcane crap like:

   obj->ops.tbl[BLAH]->func(obj, &obj->x, arg);
Want to take an integer in a register, then add another register's integer multiplied by 8 or 4, and then a fixed offset?

Just use LEA (load effective address) and don't comment anything.

Let the reader figure out that no pointers are involved.


I guess you're being sarcastic but I honestly can't tell.

[edit: 99% sure is sarcastic]


> C can be viewed as a pleasant, portable, assembly language.

Do I have to buy what you're on from some guy on the street or is it available as a prescription?

> As such, it lets you "feel" the bare metal, much more so than a scripting language like Python or Javascript.

C hasn't been bare metal since the PDP-11. There are like eight layers of abstraction between

  char *foo = "bar";
and the "bare metal"; I don't know why people are desperately clinging to this "C is basically portable assembly nonsense".


Eight layers? That made me curious about how many are there really, though? My understanding is rather vague at this level, though hopefully good enough to know when I need to look deeper.

So the compiler is obviously one layer. Then there's the assembler and the linker. Does the C runtime count too?

You think you have a "string", but it's actually just an address to a (hopefully) nul-terminated chunk of "contiguous" virtual memory.

If you wanted to read the first byte of that array, it would first go through the OS's virtual memory system, so that's one rather large abstraction. (I'm lumping in the hardware's virtual memory support here, too)

Then when you actually access a piece of "real" memory, there are a number of caches between your data and the request to fetch it. And what about the DRAM itself? Can it access only a single byte of memory at a time, or is that too an abstraction?

Instruction decoding is one or two layers at least, since chances are the processor doesn't actually execute x86 opcodes directly.

And when you run out of software abstractions, how many levels of abstraction is there in the actual hardware?

I only have vague ideas of what actually happens at this level, and whenever I stop to think about it, it's pretty amazing our software stacks work at all...


https://godbolt.org/g/q01z7n

I'm not sure what you mean by layers of abstraction (type checking? optimization?) but C code often does have a pretty straightforward translation to assembly.

Perhaps you had a bad experience and can clarify what you mean?


We had pointers already in Pascal.


New people are born, every day...


Huh? You need a mental model of your language and runtime.

If your language treats things in terms of numbered cells and nicknames, then you need a mental model of that.

If your language treats things in terms of reverentially transparent values, then you need a mental model of that.


That's programming eqivalent of giving someone an axe and telling them to go chop some trees.

For non-early-apprentice-level programming, one could also use the mental model of what's below the language runtime.


Well, it's really all quantum wavefunctions.


Back in my uni days I met a few people who found this confusing. It's one of the basic concepts of programming that, believe it or not, some people just aren't mentally equipped to grasp.


It seems that some languages provide a pretty good abstraction, memory-wise ;)




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

Search: