Closed jcgoble3 closed 3 years ago
At a high level, this is one of the real challenges of writing a book. I have to decide whether to explain things in top-down or bottom-up order. If I'm showing you two functions a()
and b()
where a()
calls b()
, which do I show first?
a()
first, then readers run into the problem you describe here where it contains code that isn't meaningful yet. But at least users understand the high level intent of where the code is going.b()
first, then everything is built on top of concepts they have previously seen. But they lose the context on where the code is going or why they are being introduced to some code. They may sit there and think, "Sure, this is nice, but what is this b()
thing even for?"There's no perfect answer here. I went with top-down because I think for most readers it's better for them to see code in an order that works from high level problem down to low level solution. That way at each step they know why the code is there even if they don't fully know what it's implemented in terms of yet. It's hard for material to stick if you don't know the motivation.
It does mean auto-complete isn't as happy, though. :(
OK, that does make sense for most cases, but I do think there are some potential improvements that can still be made. The big one that comes to mind is #include
s. I don't think it would be a bad thing or break the top-down approach you describe to add the appropriate #include
before using stuff from that header. That alone would fix a number of autocomplete problems, and the include doesn't really contribute much, if anything, to understanding the concepts; it's just mandatory bookkeeping, so it doesn't matter much when it's done from what I see.
(As a side note, I'm planning in my implementation to make a super-header, similar to Python.h
in CPython, that includes everything else so I only need one non-system header in each .c
file. That way I don't have to deal with includes at all other than the occasional system header. The expense is any header change causing Make to rebuild everything, but for a small project, that's acceptable.)
The big one that comes to mind is
#include
s. I don't think it would be a bad thing or break the top-down approach you describe to add the appropriate#include
before using stuff from that header.
Oof, that would be a ton of work at this point, unfortunately. :(
I've been working through the C half of the book this semester as a university independent study project, with the goal of finishing the book and a handful of challenges this semester and then taking it to the next level with additional features in the fall semester. (If you're interested, my implementation is at https://gitlab.com/jcgoble3/clox; I've currently completed through chapter 27).
However, I've noticed an annoying recurring problem with the book. I use Visual Studio Code as my IDE, which has a wonderful and amazing autocomplete feature if you give it the information to know what to autocomplete. Unfortunately, the book commonly writes code using field names, enum values, and macro and function names, sometimes over several code blocks, and only afterward does it go back and actually modify the struct or enum or declare the function/macro or add the include that my autocomplete needed in order to suggest it as a completion.
One particularly bad example is the first code block in 26.3.2, where there are nine cases of difficult-to-type field names, and those field names are not defined until the next block. The worst case was Chapter 17, with functions used early in the chapter not properly forward-declared until section 6.
Because I'm trying to avoid the shortcut of copying and pasting, I frequently jump ahead to where these things are defined/declared, and then jump back to the code that uses them. However, on more than one occasion, I've lost my place by doing this and missed a code block, and had to backtrack and figure out what I missed when I got a compile error.
It's a little late for me, but I think future readers working with an IDE that does smart autocomplete would appreciate having these things defined or declared properly before attempting to use them, as it's painful and frustrating, not to mention error-prone, trying to manually type out something like that 26.3.2 block I linked to without the assistance of autocomplete.