Values and objects

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sat May 10 05:09:31 EDT 2014


On Sat, 10 May 2014 17:21:56 +1000, Chris Angelico wrote:

> On Sat, May 10, 2014 at 4:15 PM, Steven D'Aprano
> <steve+comp.lang.python at pearwood.info> wrote:
>> On Sat, 10 May 2014 12:33:28 +1000, Chris Angelico wrote:
>>> 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.
> 
> I think at this point it's arguable, in that you can get so close to
> "passing a variable to a function" that it doesn't really matter about
> the distinction. But as I explained further down, it really just shows
> that "patch of memory" can be passed around, and that a variable can be
> backed by such a patch of memory.

No offence Chris, but I think this demonstrates that learning C causes 
brain damage and prevents clear logical thinking :-P

You're not passing a variable to a function. You're passing a pointer, 
which is itself a first-class value. It could be a pointer to ANYTHING, 
or NOTHING at all -- C doesn't even promise to ensure that it is a valid 
pointer, although more modern languages may. There's certainly no 
guarantee that it's a pointer to a variable. And you cannot create new 
variables -- C only allows variables to be created at compile time.

The question is not, "Can I implement some aspects of first-class 
behaviour for variables by hand?" The question is, "Are variables treated 
as first class values in C?"

If you asked, "Does Pascal have an exponentiation or power operator?", 
and I answered "Sure it does! If you want to calculate x squared, you 
just write x*x, if you want x cubed, write x*x*x, and if you want x to 
the power of twelve, x*x*x*x*x*x*x*x*x*x*x*x" you would rightfully slap 
me with a halibut. Being able to manually perform repeated multiplication 
is not the same as having the language support exponentiation. To say 
nothing of fractional exponents. "How about x to the power of one third?"

Being able to manually pass pointers to variables about is not the same 
as having first class variables. It fails on the very first hurdle, "Are 
variables treated the same as other values?"

How do I pass an int to a function? func(some_int)

How do I pass a double to a function? func(some_double)

How do I pass a bool to a function? func(some_bool)

How do I pass a variable to a function? ptr = &some_variable; func(ptr)

Does that look the same to you? The fact that you can do it at all is not 
sufficient to make it first class. It just makes it a work-around for the 
lack of first class variables in the language.

Personally, I don't imagine that there ever could be a language where 
variables were first class values *exactly* the same as ints, strings, 
floats etc. Otherwise, how could you tell the difference between a 
function which operated on the variable itself, and one which operated on 
the value contained by the value? The best you can do is for variables to 
be "second class" -- you can do these things to them, but you need 
special syntax or declarations to tell the compiler you're operating on 
the variable rather than the variable's value. E.g. Pascal and Algol have 
syntax for instructing the compiler when to pass a variable as a value, 
and when to pass the value. C gives you nothing.

I would say that C variables are *third class*. There's no compiler 
support for variables-as-values at all, but you can manually fake it a 
bit by using pointers. There is no way to tell whether the pointer 
actually points to a variable, and since arrays aren't first class 
neither are pointer-to-arrays.

Algol and Pascal are *second class*, since the compiler does allow you to 
pass variables as arguments (var parameters in Pascal, I forget what they 
are called in Algol). Likewise, Python let's you create new variables at 
runtime, or delete them, but you can't pass them around. But still, 
you're quite limited in what the language does for you, compared to what 
you have to do yourself:

x = 23
function("x", globals())  # See, I can pass a variable! Not.


>> Rather than *creating* patches of memory, malloc merely allocates it
>> from pre-existing memory.
> 
> I disagree. On a modern system with memory management, malloc can grab
> memory from the system, thus making it available to your process. Sure,
> physical memory will normally have to have been installed in the system,
> but conceptually you could have a malloc function that actually freezes
> the program, asks the user to build a new computer and turn it on,
> connects to a new service on that computer, and allocates memory from
> there. As far as your program's concerned, malloc actually does (attempt
> to) give you more room than you had.

Ha, well I guess you got me there. Perhaps a less over the top example is 
that you're running in a VM, and malloc can request more information from 
the host (which presumably has unlimited memory). Still impractical, but 
theoretically possible.

Nevertheless, blocks of memory are not *first class* because you don't 
handle blocks of memory like other values. To make a new int variable, 
you declare it: "int foo". To make a new block of memory, there is no 
declaration "block foo". Rather, you call malloc() at runtime. And it 
might fail. "int foo" can never fail.


>> 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
> 
> No no no, this is really creating them at compile time.

It certainly isn't. Here's a slightly different demonstration of the same 
principle, this time inside a function to prove that there's nothing 
special about the global namespace:


py> def demo():
...     print('spam' in locals())
...     spam = 23
...     print('spam' in locals())
...
py> demo()
False
True


> If you do this
> inside a function, the name has to be created as a local name before the
> function begins execution.

An implementation detail. CPython -- but not necessarily other Pythons -- 
use pre-allocated slots for local variables, but tries to hide this fact 
from you (it *almost* succeeds too). But those pre-allocated slots can 
represent unbound variables, i.e. variables which from the perspective of 
Python code don't exist:

py> def demo2():
...     spam = 23
...     print('spam' in locals())
...     del spam
...     print('spam' in locals())
...
py> demo2()
True
False

If you peer under the hood of the CPython implementation, the slot still 
exists, but that's invisible from Python, and just an implementation 
detail. Other implementations may not even have slots at all.


>> There are at least two other ways:
>>
>> globals()['spam'] = 23
>> exec('spam = 23')
> 
> With exec, you can do anything "at run time". Does that mean that, in
> languages with an exec action, absolutely everything is first-class? I'm
> not sure that that counts. Maybe I'm wrong.

No, you're right. That's why I said "Python variables aren't first-class 
either". But they're less second class than C or Pascal.


> Subscript-assigning to globals() is actually creating new (module-level)
> variables, though. And if Python allowed you to assign to locals()
> inside a function, then I would accept that local function variables can
> be created and destroyed at run time, but you can't, so local variables
> aren't first-class.

See above.




-- 
Steven D'Aprano
http://import-that.dreamwidth.org/



More information about the Python-list mailing list