Travis Griggs wrote: > If I were giving a talk at SPLASH (or some other suitable polyglot > conference), I might do one called “Language Design Worst Practices”. > > One of my first slides might be titled: > > Abuse Common Tokens in Confusing Ways > > * Make your language have a lot of keywords. Enough to make memorizing > them ALL unlikely, requiring constant visits to your documentation
Is 33 a lot? py> import keyword py> keyword.kwlist ['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'] > * Make sure said keywords are many of the obvious words programmers would > use in their applications (map, object, bytes, dir, etc) Luckily, Python doesn't make that mistake of making built-ins keywords. That would require making actual changes to the parser each time a new built-in function was added, as well as breaking people's existing code. Fortunately, Python has a much better system: a small set of keywords, very few of which would make useful variable names ("else = 23"), and a much larger set of regular names in a built-in namespace. py> import builtins # use __builtin__ in Python 2 py> sorted(vars(builtins).keys()) ['ArithmeticError', 'AssertionError', ... 'type', 'vars', 'zip'] There's 147 of the built-ins in Python 3.3, although a few of those aren't truly built-in, merely added at interpreter startup. The ability to shadow built-ins is not a bug, it is a feature. It's an amazingly powerful feature, and not particularly newbie-friendly, but *many* things are not easy for newbies to master or avoid abusing. - Code can override, or overload, built-ins, either at the level of an entire module, or inside a particular function. - Modules can offer functions which clash with a built-in name. E.g. reprlib.repr, math.pow. - More importantly, modules can offer stable APIs with no fear that the introduction of a new built-in function will require them to change their function's name. - Which is a special case of a more general benefit, the introduction of a new built-in name does *not* break existing code that already uses that name. Newbies misuse this feature because they still have a wishful-thinking approach to programming. One example of wishful-thinking is the common newbie mistake of wondering why their loop variable never changes: # Toss a coin until you get Tails. x = random.random() while x < 0.5: print "Heads" print "Tails" Isn't it obvious that I want x to get a new random number every time through the loop? I wish the computer understood me so I didn't need to write all the steps out. Likewise: int = 23 n = int("42") Isn't it obvious that the second use of int has to be the built-in function? I wish that the computer would understand from context which one I mean. Other newbie stylistic mistakes which can increase the chance of shadowing errors include: * Too many overly generic variable names like "int" and "str". * Insufficient use of functions and too much top-level code. When they shadow a built-in, they shadow it everywhere. * Excessively large functions that do too much. By the time they reach the end of their 300 line function, they have forgotten that they have already used "list" for a variable name. However, even experienced developers can make this mistake too. Generally speaking, it's trivially easy to recover from. Although if you're doing it *regularly* that might be a hint of deeper problems, e.g. poor variable naming skills, too much top-level code. There's no harm in calling a local variable "id", if you don't use the built-in id() inside that function. That's one of the reasons why functions exist, so that the names you use inside a function are distinct from those outside. > * Design your syntax so that you can’t disambiguate them contextually > between bind and reference Do you have an example of where Python cannot distinguish between a binding operation and a reference? > * Be sure to use it in a late bound language where no warnings will be > provided about the mistake you’re making at authorship time, deferring the > educational experience to sundry run times Python raises a SyntaxError at compile time, not run time, if you try to bind to a keyword: py> global = 23 File "<stdin>", line 1 global = 23 ^ SyntaxError: invalid syntax -- Steven -- https://mail.python.org/mailman/listinfo/python-list