Note: "victim" is not victim's real name or real IRC handle. Every word that follows is true. This conversation really happened.

<cowan> I mean, <3rdParty>'s a Cobol programmer by training.
<victim> Right.
<victim> Which I've met essentially none of.
<cowan> Cobol programmers don't use subroutines. They're too inefficient.
<victim> Dude, you need to put up warning tags.
<victim> That literally hurt.
<victim> Ow ow ow ow ow ow ow ow ow.
<cowan> Cobol uses things like PERFORM A THROUGH B, which means "execute the statement labeled A ,then consecutive statements until after the statement labeled B has been executed, then return. That's efficient.
<victim> That just takes "old school" to a new level. One that ignores the last 30 years of computer science. .
<cowan> If there happen to be lots of GO TOs before B is reached, fine!
<cowan> Cobol even has the insane ALTER A TO PROCEED TO B statement (though <3rdParty> says it, at least, is obsolete):
<cowan> That means: Look past the statement labeled A until you find the next GO TO statement (of course, the looking is done at compile time) ...
<victim> STOP IT YOURE HURTING MEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE!
<cowan> ... and patch it into being a GOTO B statement.
<victim> AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHHHH!
* victimpouts.
<cowan> Naturally, when code gets paged out, the ALTERs in the paged-out code are forgotten.
<victim> OMFG, you just don't stop, do you?
<victim> Wait a minute, wait wait wait.
<victim> The looking is done at compile time, but the altering is done at run time?
<cowan> Yes.
<cowan> After all, you might execute ALTER A TO PROCEED TO C next.
<victim> Congratulations, you just made me scream out loud. Literally. I'm not kidding.
<victim> I'm contemplating suicide for belonging to a species that could do this.
<victim> (OK, that second part is not true, but the first is)
<cowan> Dude, you're the Sail, I'm the Anchor.
<cowan> In a heavy wind, the Sail can tear itself loose if it ain't strapped down tight.
<cowan> Don't worry.
<victim> Yeah, but you're anchoring me to the fucking Scylla.
<cowan> OTOH, Cobol has some really cool features.
<cowan> Given two variables of the same structure type, you can say "MOVE A TO B" to do b = a (structure copy).
<cowan> But if you say MOVE CORRESPONDING A TO B, then A and B do not have to have the same type,
<cowan> and only the elements of A that also exist (by name) in B are copied.
<victim> That's vaguely interesting, yeah.
<victim> It's also three lines of code in most languages.
<cowan> Well, no. Suppose that A's type has fields b, c, d, e, f, g and B's type has fields a, c, e, g, h.
<cowan> Then it's equivalent to B.c = A.c; B.e = A.e, B.g = A.g
<cowan> but if you add members to A's type or B's type, the compiler generates more assignments.
<cowan> No searching through the code to make it so.
<victim> Right.
<victim> C can't do that, but any language where you can inspect structure membership by name can.
<cowan> You can do this in Python or Lisp if you go meta, yes, but Cobol compilers do it automatically.
<cowan> at full machine efficiency.
<victim> foreach in A; if B has A. = B.
<cowan> great minds think alike.
<victim> Ah.
<cowan> Back to the evils of Cobol: looping is done by things like PERFORM A THROUGH B N TIMES.
<cowan> So the loop statement doesn't need to be anywhere near the loop body, and often isn't.
<victim> These are all labels, right?
<victim> Oh fuck me.
<cowan> Yes, except when I was talking about MOVE CORRESPONDING.
<cowan> Now you can say COMPUTE A = B * C + D.
<cowan> But the real Cobol way is
<cowan> MULTIPLY B BY C GIVING X1
<cowan> ADD X1 TO D GIVING A.
<cowan> O' course, you better declare X1.
<cowan> You can add an ON SIZE ERROR to any of these arithmetic statements to say what to do
<cowan> if there is no room in X1 for the result, since it must be declared with a given
<cowan> number of digits, thus:
<cowan> WORKING-STORAGE SECTION.
<victim> NUMBER OF DIGITS?
<cowan> 77 X1 PICTURE 999999.
<cowan> Sure. All Cobol arithmetic is done in decimal digits.
<victim> Oh god, that's where pictures came from.
<victim> I've hit those before.
<cowan> Unless you add USAGE COMPUTATIONAL to the end of the picture
<cowan> in which case it can be binary or floating point.
<cowan> Note the magic 77, which means that this is not a structural variable.
<cowan> Structures are declared by starting with 01; fields and substructures are 02;
* victimwhimpers
<cowan> fields in the substructures are 03; and so on. You don't have to increment the numbers
<cowan> by one as long as you increment them.
<cowan> Unless, of course, the structure will be used to hold a record from some file,
<cowan> in which case you use FD instead of 01, of cours.
<victim> You're enjoying the hell out of this, I hope.
<cowan> You can add REDEFINES to a declaration to show that it shares storage with some other
<cowan> declared element.
<cowan> (Are you kidding? My ribs are aching!)
<victim> Are you copying this from somewhere, or doing it on the fly?
<victim> Wait, wait.
<victim> Shares storage?
<cowan> On the fly.
<cowan> Sure. Suppose your data
<cowan> has either a SSN number or a taxpayer ID number but not both.
<victim> You're telling me that a language that has decimal digits as a storage unit also has type-casting?
<cowan> Yup.
<cowan> SSN PICTURE 99-999-9999
<cowan> TIN 99-99999999 REDEFINES SSN
<victim> Oh no, you're going to pattern match to find out which it is aren't you?
<victim> It's like C enums, but in hell.
<cowan> No. You can define the SSN field and read the TIN field.
<cowan> It's like C unions.
<cowan> Horribly abused.
<victim> Oh no, it really IS type-casting!
<cowan> Sure.
<cowan> All variables are global.
<victim> Please, for the love of goth, tell me this language doesn't have pointers.
<victim> AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH!
<victim> You just threw that in there.
<cowan> More accurately, they're all static.
<cowan> But since most programmers don't use subroutines (which are called PROGRAMs)
<victim> I almost remember the difference.
<cowan> it's a distinction without a difference.
<cowan> static = stored in fixed location, but only accessible from the current PROGRAM.
<victim> Ah.
<cowan> Recursion is technically allowed, but without a variable stack it's sorta pointless.
<cowan> No pointers, no.
<cowan> Or at least only in Object-Oriented Cobol.
<cowan> Which is very recent and most Suzie Cobols (Sammy Cobols if they're female) don't know it.
<victim> There is OBJECT-ORIENTED COBOL?
<cowan> Yeah. I'm not up on the details.
<victim> So wait, you can try to do recursion, but variables are preserved throughout?
<cowan> yes.
<victim> Wooow.
<cowan> Then there's the CONTINUE statement. It does nothing.
<victim> Oh dear god. Why?
<cowan> But when you want to say THEN no-op, you say THEN NEXT SENTENCE.
<victim> Why?
<cowan> Screen I/O, sorting, and such are built-in language statements.
<cowan> You open a file with OPEN, but you don't mention the name of the file in the OPEN statement.
<cowan> Instead, you mention the name of the structured variable you want to read into.
<cowan> The actual association between the variable and the file goes in something called the
<cowan> ENVIRONMENT DIVISION up at the front. The file name has to be fixed.
<cowan> Ah, I just found out that the new, improved PERFORM A THROUGH B can now be PERFORM IN THREAD instead. Threaded Cobol.