TL;DR:
Most straight answer: Because it's BASIC
A trailing '$'-sign is the syntax BASIC defined when adding strings.
Also, the suffix is not only a type marker, but part of the name. In BASIC A
and A$
are two different variables. This is not a bug but a feature. The type is needed to distinguish them.
The BASIC language is defined to work that way. Changing this would make it a different language/add incompatibilities (*1). Much the same way that C requires parentheses around function parameters, despite that it would have been possible to go without.
It's an Atari
... how Atari BASIC maintains variables. There is a Variable Name Table that essentially assigns an index number to each variable name.
I guess that's a point where much of the confusion is originated. Atari BASIC is a very special implementation; the Variable Name Table is a prime oddity here. Atari BASIC keeps a static 128 entry table of all variables, using a unique indexing system for access. More so, this table is even static across many operations like editing - unlike variable handling in many other BASIC (*2).
But even Atari BASIC follows the rules of the BASIC language and handles A
and A$
as different variables. Simply try this:
10 A=1
20 DIM A$(3) : REM Special case only needed for Atari BASIC
30 A$="ABC"
40 PRINT A,A$
Every BASIC compatible with its forefathers will print
RUN
1 ABC
READY
This Example works only because these are two variables, different by type and name and is an inherent feature of BASIC.
That table and its behaviour is Atari specific, not part of any generic BASIC definition. So the question might be not about BASIC but rather why Atari BASIC didn't diverge and automated type detection. The answer could be that, beside a more complex parser, less readability and unclear situations it came down to avoiding incompatibility with BASIC as a language.
It's a Language Predating Atari's Implementation
My question is: Since the variable value includes the type, why does the programmer need to also include the type in the name of the variable?
Because it's part of the name? Even with Atari BASIC, the '$'-Suffix is stored in the name entry and Atari BASIC does distinguish between A
and A$
.
Maybe Atari could have left out the variable type, but then their programs would be incompatible to BASIC - i.e. be only a BASIC-like language.
Not to mention that in this case variable declaration would become mandatory to the tell the interpreter ahead of time which type a variable should have. A feature BASIC avoided on purpose for simplicity (unless one wants to increase complexity with sum types).
In other words, why can't we just do LET X="HELLO" without making it X$?
Because then the compiler/interpreter would not know what type X is supposed to be.
It knows the right-hand side of the assignment is a string, so it can just assign a string to X.
No, it doesn't, as it works simply left to right. No look ahead and no backtracking. BASIC is intended to be a simple language. For usage as well for implementation.
And if the program later does LET X=1 then the value could then be an integer.
Beside that integers are a later addition (and the fact that there is no look ahead), how to tell the compiler/interpreter that it's an integer, not a float?
Also, wouldn't that redefine the variable from string to integer? Polymorphism isn't a thing in BASIC, it's of strict type.
It's about Teaching
Beside simplicity of compiler/interpreter design, it all comes down to the fact that BASIC is intended to be basic. BASIC is a language meant for teaching people who never ever touched a computer before, nor seen one in their whole life (*3). It is about introducing concepts that are completely alien to students in the 1960s.
Teaching starts with introducing variables for numbers and giving them names. The idea that computers divide numbers in classes, like float or integer, is still to be learned way later. Then strings are added and marked accordingly and way later integers may be added and so on.
Adding variable definition ahead of usage might seem like natural to experienced users - and the way even back then 'professional' languages used - but it's an additional hurdle in the process of learning. One BASIC has avoided by usage without declaration - which implies that each occurrence had to be type qualified.
And it's about Era
When trying to understand a language of the past, it helps to look at their intention, and to remember that 1961 is not 2021. And Computers in the 60s are worlds apart from today's machinery.
From the thoughts section:
Maybe some BASICs have separate data structures for string and numeric variables and the suffix tells the interpreter which one to use.
What data structure is used is implementation, not language definition, isn't it? Also, yes, other interpreters use other structures - but all used on micro computers were created way after BASIC as a language was defined.
BASIC could be doing type checking when parsing the line, avoiding the need to check types at runtime.
That is exactly what BASIC does - just no look ahead. Also, parsing of a line is done, even in Atari BASIC only for syntactical correctness, to determine variable types, as the structures to be used do not exist at that moment in time.
Variable tables are build only at runtime.
*1 - Which Atari did anyway.
*2 - Introducing quite some unexpected trouble when not starting with NEW
*3 - Maybe except in flicks like Colossus :)
let x$=...
from left to right already knows the type of the variable before it attempts to parse the given value. Having that information sooner, rather than later, might make a difference in the size and complexity of the interpreter. On a platform that might have as little as 8K bytes of RAM, that might be important.intCounter
andstrAddress
. I.E., despite some ridicule of it, the programming profession actually ended up largely adopting the practice in a more language-agnostic way (at least up until type-identifying tools like Intellesense were widely available).