On Sat, 10 May 2014 12:33:28 +1000, Chris Angelico wrote: > On Sat, May 10, 2014 at 12:19 PM, Rustom Mody <rustompm...@gmail.com> > wrote: >> For me, Marko's comment that variables in python are not first-class >> whereas in C they are is for me the most important distinction Ive seen >> (in a long time of seeing these discussions). >> >> > https://en.wikipedia.org/wiki/First-class_citizen > > For variables in C to be considered first-class, they must, by most > definitions, be able to be passed around as parameters and return > values. Some definitions also require that they be able to be > constructed at run-time. How do C variables shape up? > > 1) Passing them as parameters. You can pass a pointer to a variable, > which is effectively the same as passing a variable to a function.
No it is not. It is nothing like passing a variable to a function. You are passing a pointer, which is itself a value. True, it is a value which you, the author, gives meaning as a pointer to a variable, but that need not be the case. It might be a pointer to a part of an array, or a record, or to some random address in memory, or a dangling pointer. C allows you to perform arithmetic on pointers, which means you can construct pointers to nothing in particular. In C, pointers are first-class values, since you can: - construct pointers at runtime; - pass them to functions; - return them from functions; - assign them to variables; - stuff them in structs or arrays. But variables are not. You cannot create new variables, nor treat variables themselves as function arguments, or return them from functions. The closest you can do is *manually* use a pointer to a variable to simulate the same effect, but this is both too much and too little: - too much, because you aren't limited to passing pointers to a variable, you can pass pointers to anything you like, or nothing at all; - too little, because you are responsible for managing the pointers, instead of having the compiler do so. In Pascal, like C, you can't create new variables, or return them from functions, or embed them in records. But unlike C, you can pass them to functions, using a var parameter to use pass-by-reference. Algol is similar, except pass-by-name instead. I guess that makes Pascal variables second-and-a-half class values. Given: procedure foo(var inside: integer); begin {...} end; begin foo(outside); end. the global variable "outside" is passed to foo where it effectively becomes the local variable "inside". Notice that we don't manually have to concern ourselves with pointers, in fact whether Pascal uses pointers to implement this or not is entirely invisible to the coder using the feature. It could be using magic fairy dust for all we know. We simply write the most direct, natural code we possibly can: foo(outside); and the compiler does whatever magic is needed to ensure the variable outside, rather than the value of outside, is passed to the procedure foo. There is nothing like that in C. You can only manually simulate it by passing a pointer to a variable, not by passing the variable itself. To argue that C pointers are "pass by reference" is like arguing that C has a garbage collector, because you can write one yourself. > The > callee can mutate your variable through the pointer. 2) Returning them. > This is a lot more dodgy, owing to the dangling-pointer issue, but as > long as you accept that the reference to a variable doesn't ensure its > continued life, I suppose this might be acceptable. Maybe. But it's > pushing it. 3) Constructing at run-time. Really REALLY pushing it. You > can malloc and call that a "variable", but it's not a variable any more, > it's just a patch of memory. In fact, all this proves is that variables > represent patches of memory, and patches of memory are first-class. It proves that pointers are first class (well, duh!). The C compiler makes very little effort to ensure that pointers actually point to anything. Nor can you create patches of memory ("I'll like an extra couple of terrabytes please"), or return them from functions, or insert them in arrays. Rather than *creating* patches of memory, malloc merely allocates it from pre-existing memory. > Not liking the results here. You might just as well define that all > Python variables must be backed by a dictionary (it's just as true as > "all C variables must be backed by memory") and then define the > first-class-variable as a combination of a dict and a key. Python variables aren't first-class either, but in fact we can get a bit closer to first-class than either C or Pascal. Creating new variables is trivial. Since they don't need to be declared, you create a new variable just by assigning to it: try: spam except NameError: spam = 23 There are at least two other ways: globals()['spam'] = 23 exec('spam = 23') You can also delete variables: del spam Now this really shows first-class-ness. We don't have to give the name of the variable as a string, as in del("spam"), we just use the variable's name. But there's no way to pass variables to functions, embed them in lists, etc. The closest we can do is pass a string, the name of the variable, and a namespace: foo('spam', namespace) To be truly first class, we ought to be able to write something like this: x = 23 alist = [1, 2, x] alist[2] = 42 assert x == 42 but we cannot. -- Steven D'Aprano http://import-that.dreamwidth.org/ -- https://mail.python.org/mailman/listinfo/python-list