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! |
* victim | pouts. |
<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 |
<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; |
* victim | whimpers |
<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. |