Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Most programming languages appear to be designed to not allow one to declare an identifier that starts with a number. I was just curious to know the reason. I have already searched the web, but couldn't find a satisfactory explanation.

share|improve this question
4  
Do you have a single example of a variable name where it would have a benefit for clarity and readability? –  Secure Feb 5 '12 at 12:56
4  
@Secure: 3dspline, 4seasonPizza, 2pdfConverter, 8bitInt, ... –  user unknown Feb 5 '12 at 18:02
6  
Forth allows it. Of the built-ins: 2DUP, 2DROP, 2SWAP, 2>R, 2R@, 2R>, 0=, etc. –  Peter Mortensen Feb 5 '12 at 18:23
    
as does TCL but I don't think any of the standard TCL commands start with a number –  jk. Feb 6 '12 at 11:49

9 Answers 9

up vote 48 down vote accepted

In C/C++, a number followed by a letter is considered to be a numeric constant and the string that follows, qualifies the type of the constant. So for example (these are VC++, not sure how standard they are):

  • 0 - signed integer
  • 0l - signed long integer
  • 0u - unsigned integer
  • 0i64 - 64 bit signed integer

So a) it is easier for the lexer as Daniel said but also b) it makes an explicit distinction since 0y might be a variable but 0u would never be. Plus other qualifiers, like "i64" were added way later than "l" or "u" and they want to keep the option open of adding more if needed.

share|improve this answer
7  
also, hex numbers are written in the form 0xd+ where d+ is 1 more hex digits 0-f -- so 0xbeef is a perfectly valid "number". –  tcrosley Feb 5 '12 at 5:46
    
It's U, L, UL, LL and ULL for unsigned, long, unsigned long, long long and unsigned long long. –  Andrey Vihrov Feb 5 '12 at 9:09
18  
you guys do realize I wasn't going for a language spec, but only provided few examples to illustrate the point, right? –  DXM Feb 5 '12 at 9:21
5  
Re: "they want to keep the option open of adding more if needed": And C++11 even lets you add your own; see http://en.wikipedia.org/wiki/C++11#User-defined_literals. –  ruakh Feb 5 '12 at 20:59
    
Also, the prefixes "f" and "d" stand for "float" and "double" –  barjak Feb 6 '12 at 10:05

The convenience of the people implementing the lexer. (No, seriously, that is about it. Various languages have other reasons, but it ultimately comes down to that.)

share|improve this answer
2  
It would easy to distinguish between integral literals and identifiers starting with digits using PEGs or other modern parsing techniques. Even compilers using primitive lexers could put them in the same token category and differentiate later. It would just be very awkward if e.g. 0flu was a literal and 0glu was a local identifier. –  Daniel Feb 5 '12 at 7:24
1  
It is absolutely possible for people to distinguish them. The decision is made based on convenience (or, if you are less charitable, laziness) rather than technical requirements. –  Daniel Pittman Feb 5 '12 at 7:58
2  
@DanielPittman: You'd need semantic analysis to do any sort of reliable disambiguation, so that can't be done in the lexer. Pushing the decision out of the lexer makes the parser more complex, and to what benefit? Besides the very poor cost/benefit situation, there is just no good way to handle a case like int 0u = 5; unsigned int x = 0u; However you choose to define the interpretation of this code (likely either x == 0 or x == 5), people are going to be confused because of the ambiguity. Even if it were trivial to implement the compiler this way, a good designer would likely not do it. –  Joren Feb 5 '12 at 10:14
10  
The main convenience is for the parser in my head, and not for the creator of the language. –  CodesInChaos Feb 5 '12 at 11:07
2  
It's still a surprise to many people to learn that lexical analysis is usually be a large factor the slowest stage of a compiler/interpreter. –  hippietrail Feb 5 '12 at 12:03

Consider the following 2 cases:

Case 1

Lets assume that an identifier could begin with a number.

So a statement like below would be valid (since an identifier can have 1 or more characters) :

int 3;

When I try to use the above variable in a program, it'll result in compiler ambiguity:

int 3,a;
3=5;
a=3;

In the statement a=3 what is the role of 3 (is it a variable with value 5 or is it the numeral 3) ?

Case 2

As opposed to the example above, lets assume that a language were to actually allow identifiers starting with a number while still disallowing numerals being used as identifiers. This can cause the following issues:

  • The language rules regarding the variable which says that a variable can consist of 1 or more characters will have to be redefined to a complex rule like: A variable can have one or more characters and must be unique if it does not start with a number while it cannot be of single character length when starting with a number (etc..)

  • The compiler will have to check for and report error cases when all numerals (eg 333) and valid alphabet suffixes (e.g. 34L) are being used as variable names. In loosely typed languages like Python and JS where you can use variables on the fly without declaring them, it may even be impossible to check for the special cases involving all numerals e.g. if (33==5) Here, 33 could be an erroneous undeclared variable that the user has declared. But the compiler will not be able to identify this and report the error.

Making this restriction will prevent the programmer from using numbers as identifier names.

share|improve this answer
2  
Under this logic, identifiers could not contain characters as they would be ambiguous to keywords. Can you imagine how disastrous int char = float would be? –  Pubby Feb 5 '12 at 13:21
3  
@Pubby : I don't see how you can extrapolate what I said to some utter non sense which I can't figure out yet. What does your comment mean? –  aml90 Feb 5 '12 at 13:27
    
I'm saying that you're taking the question too literally and that it's not at all ambiguous by using lexing precedence. For instance, how does the compiler know int is a keyword and not an identifier? Well, int has higher precedence just as numical lexemes would have. –  Pubby Feb 5 '12 at 13:39
    
@Pubby : By ambiguity I meant that the compiler would not know in what context I'm using the variable name (even using lexical precedence). For eg, consider this code: int 3,a; 3=5; a=3; In the statement a=3, is 3 interpreted as an identifier or as a number? This causes ambiguity. Hope it's clear. –  aml90 Feb 5 '12 at 13:46
2  
I also find this argument weak. It would be trivial to write a lexer that would accept identifiers that start with, but are not entirely composed of, numerals. –  Larry Gritz Feb 7 '12 at 22:59

For the most part this has nothing to do with making it easy for the compiler writers and parsing efficiency, but, more to do with designing a syntax that encourages clear readable and unambiguous code.

Its the language designers thought it would be nice to be able to write numeric literals like the number 1 as just plain 1 .

It would be quite possible to design a language syntax where numeric literals were quoted in some way for example tildas so the numberic literal for number one was encoded as ~1~ and anything not a keyword and not enclosed in quotes was treated as a variable name.

So you could code statements like:

1 = ~2~
two = 1 * ~2~

But also:

2 = ~3~
six = 2 + 2

Whatever syntax you choose ambiguous and hard to follow code is unavoidable.

The C language and most of the "curly brackets" languages descended from C also thought it a good idea to allow programmers to code Octal and Hexadecimal literals directly, and, to specify the type of the literal if this was important. So

010  // Octal 10 = 8;
0x10 // Hexadecimal 10 = 16;
5l   // long integer with decimal value 5
2.0d // double float with value 2

So even if you allowed variable names start with a number followed by a combination of numbers and letter that included at least one letter you would present the programmer with the problem of deciding whether a given group formed a variable name or a numeric literal so

2lll = 22 // OK
2ll  = 2  // compiler error

Such ambiguity would not help anyone writing or reading a program.

For a closely related real world example you could look at PL/1 language whose designers thought that being able to use keywords as variable names was a good idea so that:

IF THEN THEN THEN = ELSE; ELSE ELSE = THEN;
IF IF THEN ELSE = IF; ELSE THEN = ELSE;
DO WHILE (WHILE = DO); END = WHILE + DO; END;

Is valid code which compiles and executes.

share|improve this answer
    
C was designed as portable assembly for Unix. Unix was originally designed for an 18-bit machine, where octal is a good fit for printing in the same way hex is a good fit for printing 8/16/32-bit machine values. Hence they actually needed octal. –  user1249 Feb 6 '12 at 19:44
    
Also for bit twiddling (OR,XOR,AND,NOT) and implementing device drivers its important to specify the exact size of a literal as well as the value! –  James Anderson Feb 7 '12 at 1:33

Fortran had a huge effect on how later languages were designed. Early on (some of these problems have since been fixed) Fortran had almost no rules restricting what name you could give to an identifier. This made the language extremely difficult to parse both for compilers and for programmers. Here's one classic example:

if if .eq. then then = else else else = endif endif
K  I   K   K    I      I    K    I      I     K

Here I've marked the "language key words" with K and the identifiers (variable names) I. Given that there's no difference in spelling, I think you can probably understand how confusing this could be. Of course, this is an extreme example, and it's unlikely anybody ever wrote code quite like this on purpose. Sometimes people did "recycle" language key words as identifier names though -- and in a lot of cases a simple typo could result in code that the language spec said should be parsed this way, even though it wasn't intended at all. For another well-known example, compare this:

do 10 i = 1,10

to this:

do 10 i = 1.10

The first is a do loop -- iterating a block of code 10 times. The second, however, has had the comma changed to a decimal point, so it's assigning the value 1.10 to a variable named do 10 i.

This also meant that writing a Fortran parser was relatively difficult -- you couldn't be certain that the do at the beginning of the line was really a key word until you reached the end of the line, and verified that all the other elements of a do loop were present. The parser generally had to be ready to "backtrack", re-parsing the line from the beginning to come to the "correct" (but often unintended) answer of what was really there.

After a few years of this, language designers (most of them anyway) went toward the opposite extreme -- restricting nearly everything about the language as much as possible without the users complaining too much.

Early BASIC, for example, basically said you couldn't even use a key word as part of an identifier -- for example, fora=1 would be parsed as for a = 1 (i.e., the beginning of a for loop, not an assignment). That apparently generated enough complaints that it didn't last very long. The rule about starting an identifier with a digit apparently hasn't generated a lot of complaints, so it continues to be used (at least in most languages).

share|improve this answer
    
IMHO this is closest to the real reason. Early languages such as Fortran were, in some ways, too unstructured, leading to difficulties writing robust compilers and difficulty for humans to correctly visually parse the source code. The "do10i=..." is a classic and famous example. As languages evolved, some of the rules were tightened up. Algol is probably the grandfather of the standard "identifiers start with letters and thereafter can have letters or numbers" rule of thumb. –  Larry Gritz Feb 7 '12 at 23:02
    
FYI, the Microsoft BASIC interpreter that formed the basis of most popular Microcomputer versions of BASIC (including Applesoft Basic and Commodore Basic) used a greedy tokenizer to convert any sequence of characters which matched a language token into a byte value with the high bit set. This was done without any syntactic analysis. Then, when running the program, the interpreter would assume any letters it found constituted part of a variable name. –  supercat Jul 11 '12 at 17:11

Likely this convention has evolved from very early historical language design decisions, as on early machines the entire compiler, including lexical analysis, had to run in a few kWords, less memory than even just the first-level processor data cache on current mobile devices, so the allowed variable names were very limited, and had to be easy to distinguish from numeric constants in very few op codes.

Thus, the convention became what generations of programmers are used to.

share|improve this answer

It's not a logically required rule for programming language but just the convention used by many language designers.

I can design radically different language that allow all character for identifiers. For all code lines, first 20 character will describe the statement type then next 20 character will define the first symbol for the statement, and next 20 character is operand for the statement. This language will be executed on a stack processor.

01234567890123456789 01234567890123456789 01234567890123456789

decl symbol          12345                
assign value         12345                12345
decl symbol          99999                
assign value         99999                12345
push                 12345
push                 99999
add
print top

This code could be translated in C as below:

int i12345 = 12345;
int i99999 = 12345;
printf("%d", i12345+i9999);

That's all. It's meaningless and the no-number-in-identifiers rule is also pointless in logical ground.

share|improve this answer

In addition to "convenience for the lexer", I think it is also worth considering "convenience for the reader".

When reading code, you need to quickly and repeatedly identify which words are identifiers, and which are numbers. Looking for a digit at the beginning is easier on our visual pattern-matching; it would be a chore if we had to carefully check all the characters to make sure.

share|improve this answer

The answer to this question lies in automata or more precisely finite automata that defines the regular expression. The rule is...compilers need exact algorithms or rules to decide at every character that they parse. If identifiers were allowee to start with a number then the compiler will be in a fix..about the nature of the token coming...will it be a number or an identifier...and as compilers cant backtrack to earlier positions...so..to make it clear to the compiler that the coming token is precisely an identifier or a number...this restriction is there...coz of this...compiler knows just by scanning the first character that the coming token is an identifier or a number.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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