M: Got a question that came from a roundabout way. It would have been back in, I guess, early 1993. I was at a school where the strongest computer they had was an Apple II GS, and I still managed to use BASIC. I hadn't even really gotten around to trying to figure out assembly, but I was able to use BASIC to build a crude 3D framework rotation program that displayed a simple wireframe of the car from Danger Mouse. And in the process of doing so, and incidentally implementing the rotation keys, I kind of got— well, at that time, I was disappointed in myself for not coming up with a more elegant way to handle the inputs other than a series of if-thens, and only later on did I realize that there really was no paradigm that was more elegant in terms of programming. What I'm going to ask you to do, kind of, is to settle my own mind about the idea, because I've kind of accepted that a well-organized process loop is kind of satisfying if you think of it as like someone riffling cards repeatedly, but it still seems wasteful if I drop my guard like that and just think about how there really isn't any better way. So what I'm going to ask you to do is kind of help me settle my mind a little bit more about a possible way of looking at input loops, taking things in a different direction. What I'd like you to do is tell me the feasibility of setting up— let's exclude modifier keys for now— but a way to handle the branching of inputs not as a setup which is inserted as a sequence, but rather in a way that creates a complete binary tree using the inputs from a keyboard to build the smallest complete tree of inputs, which then would be set as kind of constant, so that, again, instead of setting up an if-then-else-if, etc., sequence for an input handling loop, the tree would be almost hard-coded as already existing, so that hooking an input onto an action was always going to be as quick as possible. And is what I'm asking making sense? I don't want to handle these things in terms of, like, ASCII interpretation. I'm talking about the raw signal coming in from the keyboard.
G: [Non-text content: reasoning_recap; content_type=reasoning_recap]
G: Yes, what you're asking makes sense.
At the raw-key level, you're essentially asking whether instead of doing this:
if key == LEFT
else if key == RIGHT
else if key == UP
else if key == DOWN
...
you could construct a fixed decision structure over the keyboard's possible hardware codes, such that each incoming key event traverses a small binary tree and lands directly at the associated action.
You absolutely could. The interesting part is that once you phrase the problem that way, you arrive very close to several real techniques used in computer systems—but also discover why programmers usually don't literally use the binary-tree version.
Suppose you have 128 possible raw key codes. A perfectly balanced binary decision tree needs only:
[ \log_2(128)=7 ]
decisions to identify any key.
So instead of potentially checking 70 conditions in an
IF...ELSE IF... chain, you're guaranteed to identify the
key in at most seven comparisons:
code < 64?
yes: code < 32?
...
no: code < 96?
...
The tree can be completely fixed ahead of time. It doesn't need to be constructed on every input cycle. Conceptually it's exactly the "hard-coded branching machine" you're imagining.
And importantly, you don't have to interpret the key as ASCII. The input can be the keyboard's hardware scan code, Apple II keyboard code, USB HID usage code, or whatever representation exists at that layer. You're just treating that incoming value as an identifier.
But here's the part that I think may resolve the thing that's been bothering you for thirty-three years:
If the incoming key code is already an integer in some bounded range, you don't actually need to search for it at all.
You make the key code itself the address.
Conceptually:
action = key_table[keycode]
where:
key_table[LEFT] = rotate_left
key_table[RIGHT] = rotate_right
key_table[UP] = rotate_up
key_table[DOWN] = rotate_down
Everything else points to do_nothing.
Then receiving a key becomes approximately:
READ KEYCODE
LOOK UP KEY_TABLE[KEYCODE]
PERFORM ACTION
There is no linear chain and no binary search.
In complexity terms:
And that's essentially the endpoint of the intuition you were having as a kid.
Your dissatisfaction with repeatedly asking
Is it A? No. Is it B? No. Is it C? No...
was perfectly reasonable. There really is a representation in which the machine doesn't have to ask those questions.
The trick is that you have to spend memory to buy that behavior.
Imagine a keyboard whose raw scan codes run from 0–127.
You reserve 128 table entries:
0 -> nothing
1 -> nothing
2 -> nothing
...
37 -> rotate left
38 -> rotate right
39 -> rotate up
40 -> rotate down
...
127 -> nothing
Now code 39 comes in.
You don't determine where 39 belongs.
39 tells you where it belongs.
That's the conceptual distinction.
Your proposed binary tree is therefore completely feasible, and actually represents a genuine improvement over a sequential IF chain. But if the input already comes in as a compact numerical key identifier, the tree is solving a search problem that doesn't really need to exist.
There's another historical twist here that I think you'll appreciate. At the machine-code level, this idea often turns into something called a jump table.
Instead of the table containing abstract "actions," it contains addresses of code:
keycode 0 -> address of IgnoreKey
keycode 1 -> address of IgnoreKey
...
keycode 37 -> address of RotateLeft
keycode 38 -> address of RotateRight
keycode 39 -> address of RotateUp
Then the CPU does roughly:
address = jump_table[keycode]
JUMP address
That is very close to the thing you were imagining as a permanently established branching structure. It's just flatter.
And CPUs have historically had mechanisms specifically suited to this. Compilers can also transform something like:
switch (key) {
case LEFT: ...
case RIGHT: ...
case UP: ...
case DOWN: ...
}into a jump table when the case values are sufficiently dense. So a
nice-looking switch statement may ultimately compile into
approximately the architecture you're describing.
There's also a satisfying way to reconcile this with your card-riffling image.
A sequential input loop is:
"Rifle through the deck until I find the card."
Your binary tree is:
"I've organized the deck into nested halves, so I can find any card in seven cuts."
A lookup table is:
"Every card has a numbered slot. The number on the card tells me which slot to open."
The third one is why your childhood instinct that there ought to be something more elegant than a pile of IF statements wasn't actually mistaken. You just didn't yet have the vocabulary—or, probably, convenient BASIC machinery—to express the alternative.
And there's one additional distinction worth making: the polling loop itself isn't wasteful in the same sense. Even with a perfect jump table, something somewhere still has to notice that an input event occurred. On older systems that might mean polling a keyboard register; on more sophisticated systems an interrupt/event mechanism can arrange for the keyboard hardware to effectively say, "Hey, I have something," rather than the program continuously asking.
So there are really two separate problems:
WHEN did a key happen? polling vs interrupt/event
WHAT key was it? IF chain vs tree vs lookup table
WHAT should that key do? jump table / function table / mapping
Separating those three makes the whole subject much cleaner.
And for what you were doing on an Apple IIgs in BASIC in early 1993,
a bunch of IF statements was not evidence that you'd
somehow failed to discover the elegant solution. You had encountered a
genuine computer-science problem and independently noticed the
inefficiency that leads toward decision trees, dispatch tables, and
ultimately direct indexed dispatch. The language and level you were
programming at just made the least elegant representation the easiest
one to express.
M: It's late in the night or early in the morning for me to completely comprehend what you're saying, but I see your point. The problem is it seems like for implementation at the 1993 level I was working with, it would have required basically leaving BASIC, or the paradigm that I was aware of. At that point I was trying to transfer over into object-oriented programming. I just was having trouble. Well, I was thinking about it tonight, and I think in retrospect I was not so much having trouble leaving the paradigm behind as I was having trouble finding reasons to practice enough to figure out how to get things done more efficiently, or outside inspiration. It's easy to forget that back then finding modern information was costly, either in resources or time. And that was before I was diagnosed with autism. So, oh, and also hadn't really bought into the idea that I actually liked interacting with people; I just didn't know how to do it yet. So all of that combined into a situation where I was a very isolated proto-nerd, but without the drive to actually take it into the area of just, you know, figuring things out for the knowledge's sake. I was thinking this way because I found out about how in the '80s there was at least one, and probably more, magazines in Japan where they literally would just print out various games in BASIC, although it was very specific BASIC, from what I could tell, and in doing so would give clues as to how to make shortcuts, and by doing so gave a kind of reason to try and learn something besides the learning itself, just as a challenge rather than a pile of knowledge. There either wasn't a parallel to that in America, or I never was able to find it, or I had the bad luck not to run across it, which wouldn't surprise me because the only proactive nerd I ever knew I only knew for like a year before he left the school. Anyway, would the tree approach have worked back then with BASIC, or would it have been too difficult to implement? I'm asking in general, because for the project I was working on at that point, I only needed a few keys, so it really wasn't a loss. But what you're talking about with lookup tables and all of that, I'm not sure if that actually could have been practically implemented with a 2GS. And then when it started getting into object-oriented stuff, even though the lookup table thing was there, the way it was presented, like as an introduction to maybe slightly intermediate ways of dealing with things, it still was being presented as big old if-thens, rather than attempting to offer that maybe there were other solutions that were a lot more efficient and less discouraging.
G: Yes — the distinction you’re making is important: not “could a computer scientist devise it?” but could you, in ordinary BASIC on an Apple IIgs around 1993, have implemented it without effectively changing programming worlds? I’m checking that historical layer, because the answer depends a lot on what BASIC actually exposed conveniently on the IIgs.
G: [Non-text content: thoughts; content_type=thoughts]
G: [Non-text content: reasoning_recap; content_type=reasoning_recap]
G: Yes. If by “BASIC” you mean the ordinary Applesoft BASIC environment you were likely using on that IIgs, the binary-tree approach was entirely implementable without leaving BASIC. It would have been somewhat awkward, but not remotely beyond the language.
And after checking the historical context, I think there's a second part of this that may be more significant: the kind of educational ecosystem you're describing absolutely existed in America, including one specifically for the Apple II—but you could very plausibly have missed it. In fact, one of the best examples, Nibble, had just ceased publication in July 1992, essentially right before the period you're talking about. citeturn269191search1turn269191search39
Suppose you had eight possible raw-ish key values that mattered. You could write something conceptually like:
100 K = PEEK(49152)
110 IF K < 132 THEN GOTO 200
120 IF K < 136 THEN GOTO 300
130 GOTO 400
200 IF K < 130 THEN GOTO 210
205 GOTO 220
210 REM FIRST QUARTER OF KEY RANGE
220 REM SECOND QUARTER
300 IF K < 134 THEN GOTO 310
305 GOTO 320
That's ugly by modern standards, but structurally it's exactly your tree.
Instead of:
Is K=A?
No.
Is K=B?
No.
Is K=C?
No.
Is K=D?
...
you're asking:
Which half?
Which half of that half?
Which half of that?
So for 16 possible inputs you'd need no more than four decisions; for 128 possible values, seven.
Nothing about that requires assembly language, object orientation, or
even advanced BASIC. It's just nested comparisons and
GOTOs.
So 1993-you could absolutely have discovered and implemented your idea using the tools you already knew.
The problem is that Applesoft would have done very little to lead you toward thinking about the problem that way.
That's an important distinction.
This is where my previous answer was slightly misleading in relation to your actual historical situation.
A modern programmer sees:
action[keycode]()and thinks, “Of course.”
Applesoft BASIC did not give you ordinary function pointers, delegates, objects with methods, or anything comparable. And the version of Applesoft present on the IIgs was essentially still the old late-1970s BASIC. It could only use the lowest 64K of the machine and largely behaved like Applesoft on the earlier 8-bit Apple IIs. citeturn269191search3
You could nevertheless fake a dispatch table.
One very BASIC-ish method would have been an array containing line numbers:
10 DIM A(127)
20 A(37)=1000
30 A(38)=1100
40 A(39)=1200
50 A(40)=1300
and then something along the conceptual lines of:
100 K = ...
110 ON A(K) GOTO ...
although Applesoft's particular ON ... GOTO syntax and
the need for sequential branch targets make that less wonderfully direct
than I've drawn it there. You could devise variations using arrays,
calculated values, or self-imposed numbering conventions.
And once you started using PEEK, POKE,
machine-language routines, or calculated addresses, you could get
progressively closer to a genuine dispatch table.
But at that point the complaint you're making becomes valid:
“Okay, but now I have to know that this is a thing one might want to do.”
Exactly.
The machine was capable of it. BASIC was capable of enough machinery to approximate it. But there wasn't a natural pedagogical path from beginner BASIC to “represent control flow as data.”
That's a relatively sophisticated conceptual jump.
There's also an amusing historical mismatch in the machine you were using.
The IIgs itself was a 16-bit machine built around the 65C816, with a much richer operating system and programming toolbox. Yet if you entered Applesoft BASIC, you were effectively sitting inside a compatibility environment inherited from an Apple II Plus-era language.
Apple II historians describe Applesoft on the IIgs as essentially the same ROM language from 1979. More capable IIgs BASICs existed—AC/BASIC, TML BASIC, Micol Advanced BASIC—but by roughly 1992 most IIgs-specific BASIC products had either disappeared or failed to gain much traction. Programmers wanting serious IIgs development were increasingly expected to move into Pascal or C. citeturn269191search3
So the educational path available to someone in your situation was almost perversely discontinuous:
BEGINNER WORLD
10 PRINT
20 INPUT
30 IF X=1 THEN...
40 GOTO 10
↓
some poorly illuminated chasm
↓
SERIOUS PROGRAMMER WORLD
C
Pascal
assembly
IIgs Toolbox
event handling
data structures
pointers
And object-oriented programming doesn't necessarily solve the problem you're describing anyway.
That's another thing I think your retrospective diagnosis gets right.
You might have thought:
“I'm having trouble moving from BASIC into this more sophisticated programming paradigm.”
But the particular insight you were missing—“instead of encoding every decision procedurally, encode the correspondence between inputs and behaviors as a structure”—isn't fundamentally an OOP insight.
It's a data-structures / indirection / dispatch insight.
You can write horrible chains of if statements in
C++.
You can write elegant table-driven programs in BASIC.
OOP wasn't necessarily the bridge you needed.
And now we get to the magazine thing, because this is where there's a rather painful historical coincidence.
America absolutely had the thing you wish you'd encountered.
COMPUTE! ran from 1979 through 1994 and routinely printed complete type-in programs—games, utilities and applications, usually in BASIC, often with versions for several different computers. citeturn269191search33
But much more specifically for you, there was Nibble.
It was an American magazine devoted to Apple II programming, begun in 1980. It published everything from simple Applesoft programs through complicated games, BASIC extensions and assembly-language material. Its own retrospective explicitly describes it as a place where people learned programming from well-commented listings and could inspect the techniques used by other programmers. citeturn269191search1turn269191search4
And this is almost uncannily close to the educational mechanism you're describing from those Japanese magazines. One surviving discussion of a Nibble issue describes a 168-line Applesoft mystery game whose listing was accompanied by a “How the program works” section explaining its routines rather than merely giving readers code to copy. citeturn269191search5
They even had a regular feature called “Disassembly Lines” that took pieces of Apple software apart and explained the assembly-language techniques underneath them. citeturn269191search39turn269191search4
There were books spun out of it with titles including Applesoft Power Tools, Hands On Applesoft, Apple Secrets, 1, 2 and 3 Minute Apple Programs, and several volumes of Disassembly Line. citeturn269191search0
In other words:
The missing mentor you are describing basically existed in magazine form.
And then comes the unfortunate part.
Nibble's last issue was July 1992. citeturn269191search39
You're describing being in that school in early 1993.
Moreover, by 1991 Nibble had already stopped normal newsstand distribution and gone subscription-only, because declining Apple II interest, printing costs and advertising problems were squeezing it. citeturn269191search4
So had this happened five years earlier, you might have wandered into a bookstore or computer shop and found precisely the publication you're now imagining.
Instead, you came along at essentially the moment that entire American home-computer programming culture was disappearing.
That strikes me as considerably more explanatory than “I wasn't sufficiently driven to teach myself programming.”
You had an obsolete-but-accessible programming environment on a much more capable machine, were being encouraged toward substantially more complicated development environments, had no Internet in the modern sense to bridge the gap, and one of the most relevant educational publications for your exact computer had vanished from newsstands and then ceased publication months before.
And there's actually a wonderful little data point from the end of Nibble. Its February 1992 issue—only a year before your project—contained articles on 16-bit BASIC, an Applesoft programming utility, a medium-resolution shape generator inside a game listing, and a machine-language routine for speeding searches. citeturn269191search41
That's exactly the continuum you were missing:
Here's a game.
Here's how the game works.
Here's a trick BASIC can do.
Here's why BASIC is slow at this particular operation.
Here's a little machine-language routine that improves it.
Here's how that routine works.
Rather than:
You've learned BASIC.
Now learn C++.
And I think that also explains why your Japanese magazine discovery kicked off this train of thought. Challenge-driven learning through other people's small programs was one of the major informal ways people learned programming in the 8-bit era. You weren't imagining an educational paradigm that didn't exist; you had simply missed the channel through which it was commonly delivered.
As for the original 3-D car program: with only four or six rotation
controls, your IFs were probably the better engineering
decision anyway. A four-key balanced tree saves, at most, a couple
comparisons while making Applesoft source substantially harder to
understand. The tree becomes interesting once you're dispatching dozens
of inputs. So there are two different verdicts on 1993-you:
Your intuition that a long linear sequence ought to be replaceable by a structured branching system was correct. You could have built that system in Applesoft BASIC.
Your decision not to invent it for a handful of rotation keys was also, inadvertently, correct.
The missing insight wasn't really “how do I write better IF statements?” It was the much larger idea that control flow itself can sometimes be turned into data. Once somebody shows you that trick through an interesting program, a whole family of things—lookup tables, state machines, dispatch tables, maps, function pointers—starts becoming much easier to discover. memcite
M: The funny thing is that before starting on the object-oriented path, I had been focused more on the idea of object-oriented programming using GoSub. I think that actually was how I got the 3D stuff to work by basically building functions in BASIC in the same conceptual way as functions came around, just without the actual label. Which, on one hand, indicated an interesting personal development of the concept before I ever encountered it. But on the other hand, definitely implies that my approach was becoming more generic, while you're saying that in order to implement the kind of... how would I put it? Resource elegance that I'm talking about right now, it would have required much more precision, or at the very least, an outside source indicating the necessity of that precision, which likely could have been folded into the GoSub methodology, but wouldn't have naturally come about given that I was thinking about making things more encompassing, while the kind of specific references you're talking about are kind of on the opposite end of the thought spectrum, for lack of a better way of putting it. So it's not even a question of my simply trying to expand on the beginner stuff and make as much use of it. It's that I was actually expanding into an advanced area, just opposite in the direction from what we're talking about right now. I was aware of Assembler and had looked at it. I just hadn't found any good documentation. So I knew about the various stuff. I just wasn't able to find any kind of capacity to go from the conceptual stuff of BASIC and bridge over into the really root stuff of Assembler. And I wasn't aware of the basic capacities in a way that you would be using documentation now, because, like all of the books I could find were at least a few years old, if not more, and I really couldn't afford to go out and find better books, and even if I could, a lot of them were just new reprints of the older books. And I hadn't gone online yet. And I was autistic, so even if I had gone online, I wouldn't necessarily have been able to interact with people well enough to get any new information. It's funny because as you're talking, as I'm going through your response, you kind of went the same direction I did with my rambling in terms of the object-oriented. And I appreciate your trying to comfort me, but a review of my own motivations over the last few decades says that this isn't self-recrimination, but just acknowledgement that learning something just for the sake of learning is kind of an iffy proposition for me. Like after the novelty has worn off, I want something to apply that knowledge to and keep learning more. Otherwise, I tend to just kind of put it up on a shelf mentally until the time arises where I have a reason to get further into it, which is why I brought up the whole thing about not running into any proactive nerds. There was really no one out there saying that they either were doing something I wanted to keep up with, or wanting to do something but not knowing how that I could figure out.
G: Yes. I think you've identified two different axes of “becoming a more advanced programmer,” and you were moving quite a long way down one while assuming that eventually it would lead you to the other. It doesn't necessarily.
What you were doing with GOSUB was moving toward
abstraction:
Instead of writing the rotation mathematics here,
put it somewhere else
give that operation an identity
pass control to it
come back when it's finished.
Even without formal functions, that's procedural decomposition. If you were also starting to think of the routines as belonging to conceptual things—the car has rotation operations, the display has drawing operations, etc.—then you're edging toward the conceptual territory that structured and object-oriented programming formalized.
The input-table idea goes almost orthogonally to that. It's moving toward representation and indirection:
Don't ask "what procedure should I write to distinguish these things?"
Ask "can I arrange the information so that
the value itself tells the computer what to do?"
Those really are different directions.
You could become extremely good at decomposing a program:
MAIN
GOSUB GETINPUT
GOSUB ROTATE
GOSUB PROJECT3D
GOSUB DRAW
GOTO MAIN
and never spontaneously arrive at:
INPUT → ARRAY INDEX → ACTION
because the first process rewards making code more general and conceptually organized, whereas the second often begins by getting extremely interested in the specific representation of a value inside the machine.
That's very close to the opposition you were trying to describe.
And assembly would have supplied an especially useful bridge because it forces questions BASIC mostly permits you to ignore:
What exactly is in this byte?
Where is it in memory?
If this byte contains 37, can I use 37 to calculate an address?
Instead of comparing 37 against a bunch of possibilities, can I make the representation itself do some work?
Once you're thinking that way, a lookup table becomes almost obvious. But it is not obvious from the abstraction direction.
In fact, your GOSUB approach and that lower-level
approach could eventually have met in a rather elegant place. You might
have started with:
INPUT HANDLER
|
+--- LEFT → GOSUB ROTATELEFT
+--- RIGHT → GOSUB ROTATERIGHT
+--- UP → GOSUB ROTATEUP
and eventually realized:
Wait. The only thing changing is which subroutine I select. Can the selection itself become data?
That's the conceptual bridge from procedural decomposition into dispatch. But somebody—or some interesting program—has to give you a reason to ask that question.
I wasn't intending “you should forgive yourself for not learning more” as strongly as it apparently came across, but your distinction makes the situation much clearer.
You're not describing an inability or reluctance to learn difficult material. You're describing application-driven learning.
Something catches your attention → you need knowledge to make it work → acquiring the knowledge reveals another possibility → that creates another problem worth solving → and the chain continues.
Whereas:
Chapter 7: Advanced Memory Management
without anything you presently want to do with memory management has a good chance of becoming:
Interesting. I now know that exists. Shelf it until required.
That's a very different learning mechanism from the stereotypical teenage computer obsessive who discovers assembly and spends six months learning assembly principally because assembly exists.
And that makes the absence of the other “proactive nerd” more consequential than merely not having somebody to socialize with. Such a person can be an external problem generator.
They show up and say:
“I figured out how to make sprites move without erasing the background.”
And now there's something to investigate.
Or:
“I want to make this game, but I can't figure out how to have twenty enemies.”
Now you have a problem to solve.
Or even:
“Look at this insane thing somebody did with a lookup table.”
Suddenly the chapter on arrays isn't abstract information anymore. It's a tool.
That Japanese type-in-magazine model provides essentially the same stimulus asynchronously. The program is the proactive nerd. Someone has already decided that a particular thing is worth making, and the listing presents a succession of concrete puzzles:
Why did they do that?
That's shorter than what I would have done.
What the hell is thisPOKEfor?
Why are these numbers inDATAstatements?
Oh—that's the shape.
Wait, if they're storing that as data, could I store this as data too?
That's an enormously different experience from reading a reference manual.
And it explains something about your assembly problem particularly well. What you needed probably wasn't really better assembly documentation in the first instance.
You needed something like:
HERE IS A BASIC PROGRAM YOU UNDERSTAND.
It does X.
X is annoyingly slow.
Here are the 12 lines responsible.
Here is a tiny assembly routine replacing those 12 lines.
Here is what each assembly instruction corresponds to
in the BASIC algorithm you already understand.
Now change this one thing and see what happens.
That would have built the bridge.
Instead, if the available material effectively said:
LDA = Load Accumulator
STA = Store Accumulator
LDX = Load X Register
...
you could understand every sentence and still reasonably wonder:
“Okay. Why do I want to do any of this?”
That's not a missing intellectual step so much as a missing project context.
And there's a nice irony in the 3-D program itself. You'd independently encountered two reasonably advanced ideas, but only one supplied its own motivation.
The 3-D mathematics gave you an immediate reason to invent procedural
abstraction: repeating all that machinery everywhere was intolerable, so
GOSUB became function-like organization.
Input handling didn't supply the same pressure. Four or six
IFs worked. The inelegance irritated you, but there wasn't
enough practical cost to force discovery of another paradigm.
The program itself stopped teaching at exactly that
point.
Had the next project been a keyboard-controlled game with forty commands, the irritation might have crossed the threshold where you'd start experimenting with arrays, calculated branches, scan codes, or something similarly strange. And that might have been the project that accidentally pulled you downward toward machine representation rather than upward toward abstraction.
So I think your “opposite direction” formulation works very well. I'd just make it two-dimensional rather than treating them as literally opposite:
MORE ABSTRACTION
↑
procedures
GOSUB
functions
objects
|
|
BASIC surface ←--------+--------→ MACHINE REPRESENTATION
bytes / addresses
tables / indexing
indirection
assembly
You were already climbing the vertical axis. What you lacked wasn't the next rung. It was something interesting enough to make you turn right.
And, incidentally, the Japanese-programming-magazine connection makes a nice bit of Japanese vocabulary practice here: 工夫(くふう) means something like ingenuity / devising a clever way of doing something. A type-in program gives you somebody else's 工夫(くふう) to reverse-engineer—which seems remarkably close to the learning stimulus you're describing. memcite