On Sat, 19 Dec 2009 04:04:51 +0100, Alf P. Steinbach wrote: > * Steven D'Aprano: >> On Fri, 18 Dec 2009 19:00:48 +0100, Alf P. Steinbach wrote: >> >>> In fact almost no Python >>> code does, but then it seems that people are not aware of how many of >>> their names are constants and think that they're uppercasing constants >>> when in fact they're not. E.g. routine arguments >> >> Routine arguments are almost never constants, since by definition they >> will vary according to the value passed by the caller. > > I'm sorry, but that requires a definition of "constant" that explicitly > excludes routine arguments,
/s/explicitly/implicitly > which is like saying horses are not mammals, just "because". No, it's like saying that horses are not apes, because the definition of apes excludes horses. But in any case, rather than continue my argument (which was absolutely brilliant and flawless, I might add... *wink*), I'm going to skip ahead to the place where the penny drops and I understand what you were trying, but failed, to say. > Consider some C++ code: > > void foo( SomeType const v ) > { > // Here the name v is constant: that name's value can't change. > // (Except that in C++ you can do anything by using low-level > stuff.) > } *penny drops* Ahaha!!! Now I get it! You want to make the *parameter* of the function a constant, rather than the *argument* passed to the function. In other words, you want to prohibit something like this: def f(x): y = x + 1 # do something with the value passed by the caller x = 0 # changing the binding will fail INSIDE the function while still allowing the caller to call the function with variables. Right -- now what you say makes sense, and is a perfectly reasonable thing to do in languages that support constants. You weren't clear about what you wanted, and the only thing I could think of which matched your description was something completely bizarre: given some function f with one parameter, you wanted to declare that parameter as a constant with some value (say 42), so that calling the function with an argument of any other value would be an error, e.g.: x = 42 f(x) # succeeds x = 43 f(x) # fails E.g. implemented something like this: def f(x): if x != 42: raise ConstantError('x is not the constant 42') ... except that the test is done automatically by the compiler. > To be pedantic, original routine names are usually absolutely not meant > to be assigned to. > > If you have > > def foo(): whatever() > > you simply shouldn't, in general, do > > foo = bar > > I think you understood that, i.e., that the above comment of yours is > just rhetoric? First of all, I think you're underestimating the usefulness and frequency of rebinding names to functions. I'll accept that it's uncommon, but it's not *that* uncommon to justify "absolutely not meant to be assigned to". In fact, it's so common that we have special syntax for one special case of it. Instead of: def f(): ... f = g(f) we can write: @g def f(): ... While decorator syntax can only be used at function-definition time, the concept of function decoration is far more general. You can decorate any function, at any time, and doing so is very, very useful for (e.g.) debugging, logging, monkey-patching, introspection, error-checking, and others. And decoration itself is only one special case of function rebinding. As for your second point, my earlier comment is mostly aimed at what I see as your misleading habit of referring to *names* as being constants, rather than the value assigned to the name. Such terminology is misleading. So if you want to call that rhetoric, I won't argue. >> As far as I know, no programming language provides a standard facility >> for renaming entities, be they data or routines: > > Eiffel (IIRC) and C++ come pretty close. > > E.g., in C++: > > int a; > int& b = a; // A new name for a. > > b = 123; // Assigns to a. No, that's not a renaming operation. a still exists; you haven't told the compiler "stop accepting a as the name for this memory location, and accept b instead". It's an aliasing operation: name b and name a both refer to the same memory location and hence the same value. Even if C++ had an operation for "delete this name from the compiler's symbol table" (equivalent to del in Python), that's still a two-step process: create a new name that co-exists with the original name, then delete the original name. The fact that the C++ designers didn't see fit to give the language a way to change a name demonstrates that it's not the mutability of *names* which matter, but of *values* assigned to the names. I can think of a language where it would probably be possible, but non- standard, to write a rename instruction: Forth. It should be possible to use the tick instruction to get the address of a variable, constant or function, then directly manipulate the compiler's dictionary (not like Python dictionaries!) to change the name. But even Forth doesn't provide a rename instruction as standard. > Well, you're off on the wrong track as far as convincing me about > something is concerned. First, your belief about renaming not being > supported by any languages is largely incorrect, as shown above. > Secondly, I was not talking about renaming things -- that creative > interpretation is pretty meaningless... But if you talk about mutating *names*, then what else could it mean than that you want to change the *name*? I can only respond to what you write, not what you were thinking. You wrote "routine names are usually constants, absolutely not meant to be modified". Forget all about routines. If you had written: "int names are usually constants, absolutely not meant to be modified" then I'm sure you and I would agree: such a claim confuses the name with the value assigned to the name. It's literally true that given an int n, it is not usual to modify the *name* n regardless of whether n is a variable or a constant. But that's irrelevant to the question of whether n is a variable or a constant. That depends on the *value* assigned to n, not the name itself. Exactly the same applies to functions. If you think I'm harping on a trivial point of terminology, I guess you're half-right: I can *guess* what you mean to say, namely that function objects themselves are meant to be unmodified, and in Python it is unusual to rebind names once they have been bound to a function. (Unusual but not vanishingly so.) But that's just an assumption, and you know what they say about assumptions. Judging by what you actually say, and not what I assume you mean, your reason for believing functions are constants is incorrect and illogical. In languages that treat functions as constants, functions aren't treated as constant because the name of the function is unchangeable (since variables have unchangeable names too). They do so because the value (the function itself) is unchangeable. -- Steven -- http://mail.python.org/mailman/listinfo/python-list