14

Many early compilers and interpreters had maximum length for variable and function names. Usually you could use longer names but everything beyond e.g. the first 8 characters was discarded.

This required putting as much distinguishing information to the beginning of the symbol name as possible.

However, a simple alternative would have been to hash the rest of the name and use that to mangle the symbol name. For example "CountAllWidgets" could become "Coun012A" or similar. In common usage this would reduce the likelihood of name collisions, with the downside that it would become more difficult to predict which symbol names would collide.

Did any compilers actually do this: replace truncated part of symbol name with a hash?

11
  • 9
    I Don't know the answer, but if I were designing a language, I would argue against doing that because I'd want to keep the language specification unambiguous and simple. If I say that only the first 8 characters are significant, then everybody understands that. If I say that it's the first 8 characters plus the hash of the rest, then how does that help a programmer to know whether two identifiers are unique or not? Must the language spec also say how the hash is computed? If not, then programs that work on one platform might not work on another. It's much simpler to just say "the first 8..." Sep 28 at 15:19
  • 4
    Aside from the technical arguments against this, back in the day when you entered code with a card punch or at best a teletype, with no cut-and-paste and no autocomplete, you never used a 3-character variable name when a 2-character name would do! Calling something "CountAllWidgets" would have been a sign of serious quiche-eating disorder :)
    – alephzero
    Sep 28 at 16:49
  • 1
    As a "long variable names considered harmful" anecdote, I once took over work on a FORTRAN program written in Germany (and of course with no documentation whatever). Figuring out the German abbreviations for variable names was mostly OK, except for one mystery named KORSCH. That was "obviously" German for something, but dictionaries didn't help, and this was before the Internet era. Eventually we realized it was an English abbreviation, from a version before the Germans had worked on the code, for "Correction switch" - spelled with a K because that made it an integer by default in FORTRAN!!
    – alephzero
    Sep 28 at 16:57
  • 8
    @alephzero I'd assume KORSCH to be an abbreviation for "Korrekturschalter", as "Correction switch" even with a K would more likely be abbreviated "Korsw" or something. Sep 28 at 18:05
  • 4
    @SolomonSlow - agree, That seems negatively useful. As a programmer "must be unique in the first N chars" is easy to understand. "Subject to arbitrary collision", along with "diagnostic messages may not match source identifiers", not so much. Sep 28 at 22:42
21

I can't speak to whether any compilers did this.

I can only examine why they probably didn't.

The simplest reason is performance.

Hashing is CPU intensive. Having to hash every single identifier gets expensive quickly. The value of the extended identifiers is low in contrast to the repeated CPU load and burden this puts on the compiler.

You said "a simple alternative". But it's not simple. CPU cycles were precious back in the day. Very precious. Folks spent inordinate amounts of time to reduce cycle counts, and reduce memory. We had to suffer through more than just short identifiers to get code written back then.

Also, by the time CPUs started to actually speed up to where we could "afford" to do this in terms of CPU budget, we already more of a memory budget to wit it would become unnecessary.

Finally, the actual limitation had minimal impact. Folks wrote very large BASIC programs back when the variables were limited to 2 letters or a letter and a number. 936 identifiers. I recall working with a lady and the warehousing system she had written. She extolled her use of "Z9" as her global error variable. When it came to identifiers, we had enough, we had bigger fish to fry to get projects written.

As with many things back then, it would have been a "nice to have", but we couldn't afford it.

Addenda:

Actually I have thought of an example where hashing was used.

I believe in early versions of Forth, the dictionary used a mechanic where it stored a limited amount of letters of the identifier, but it also stored the length. Other languages, perhaps BASIC, may have done this too.

So, let's say it stored 2 letters (I don't recall the actual value), THIN and THING would, indeed be different even though internally only T H were stored because the length, 4 and 5 respectively, was also stored. Now, THIN1 and THING would be identical. But it did allow the identifier space to be expanded somewhat, and this is certainly a form of hashing.

Also, in later Forth implementations (F83 does this), the dictionary was threaded in to 4 different parts in order to speed up lookups. It hashed each identifier to discern which thread it would go on. Mind, this, again, was trivial hashing -- it was just breaking the vocabulary in to 4 different parts. It just took the bottom 2 bits of the first character of the identifier. But, it was hashed, just not directly for the purposes suggested here.

4
  • 2
    Programs were much shorter then, also programmer's were used to performing ordinary daily workarounds for deficiencies in tools. All languages, including - perhaps especially - assembler - had this limit (some to a much greater extent). And programmer time, as a resource, was just as expensive then as it is now. Perhaps more. For the tool writer as much as the tool user. It just wasn't worth the effort on anyone's part compared to how much else there was to do.
    – davidbak
    Sep 28 at 15:14
  • 5
    "Back in the day" there was no universal standard for encoding characters. Even by 1980, IBM, PDP, CDC and ICL all used their own encodings that were different from ASCII, and not all with the same number of bits per character. A "transportable standard" for hashing would have been more or less impossible to define.
    – alephzero
    Sep 28 at 17:53
  • 2
    Nice - the "length of identifier" is certainly application of the same principle. I agree with your analysis of why it wasn't very common, and I'll probably accept this answer in a few days :)
    – jpa
    Sep 29 at 6:09
  • +1 nice answer. Adding to your last paragraph: Many compilers internally use a symbol-name hash table for speed. Then they check the original full symbol name in order to detect internal hash collisions and correct them "as if" it's always comparing the full symbol name against every symbol name in the table -- they never "truncate" them as suggested by the original question. Such compilers include several GNU compilers (GNU C, GNU C++, GNU Java, etc.) use a hash table based on "gperf"; (Most?) Forth implementations use dictionary hashing to break the dictionary into 16 or so chains; etc.
    – David Cary
    Sep 29 at 20:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.