A question on modification of a list via a function invocation

Steve D'Aprano steve+python at pearwood.info
Wed Sep 6 08:58:59 EDT 2017


On Wed, 6 Sep 2017 05:12 pm, Antoon Pardon wrote:

[...]
>> I'm not saying that we should never use this model. Its a good model. But we
>> should be clear that it is a model of the implementation, and it describes
>> entities which are not part of the Python language. We cannot do this:
>>
>>
>>      +-----+
>>      |     |
>>      |  5  |
>>      |     |
>>      +-----+
>>         ^
>>         |
>>        <x>
>>         ^
>>         |
>>        <y>
>>
>>
>> or any of the other things we can do in a language with references-as-values,
>> like C or Pascal.
> 
> I don't agree that the above is an accurate picture of C or Pascal.

I'm surprised. You can do this in Pascal:

type
  intpointer = ^integer;
var
  x: intpointer;
  y: ^intpointer;
begin
  new(x);  {reserve memory in the heap for an integer, and point x at it}
  x^ := 5;
  y := @x;  {y points to the pointer x}
end.

which would translate to the diagram above. If you don't like the fact that I'm
using the "address of" operator @ which is non-standard Pascal, I can write
this instead:


type
  intpointer = ^integer;
var
  y: ^intpointer;
begin
  new(y);  {reserve memory in the heap for an intpointer, and point y at it}
  new(y^);  {reserve memory in the heap for an integer, and point y^ at it}
  y^^ := 5;
end.

I would be shocked if C were less powerful in this regard than Pascal.

 

> It is more 
> like the following:
> 
>      +-----+     +-----+
>      |     |     |     |
>      |  5  |<----+--*  |
>      |     |     |     |
>      +-----+     +-----+
>         ^           ^
>         |           |
>        <x>         <y>


That would be equivalent to a different piece of code:

type
  intpointer = ^integer;
var
  x: intpointer;
  y: ^intpointer;
begin
  new(x);  {reserve memory in the heap for an integer, and point x at it}
  x^ := 5;
  new(y);  {reserve memory in the heap for an intpointer, and point y at it}
  y^ := x;  {assignment copies; y^ now points to the same thing as x}
end.


These two are not the same thing.


> And in case of a VAR parameter in Pascal like
> 
> procedure f(VAR x);
> f(y)
> 
> one could use the following, which is the same
> as after an assignment in python.
> 
> 
>                   +-----+
>                   |     |
>                   |  7  |
>             --->  |     |
>            /      +-----+
>           /
>          /           ^
>         /            |
>       <x>           <y>

No no no! Pascal VAR parameters are not the same as Python assignment! You
cannot write a Pascal swap procedure in Python!


Pascal VAR parameters are, in a sense, syntactic sugar for pointer manipulation.
(I'm not sure just how far we can take this analogy, but I think its pretty
far.) That's probably why C didn't bother with VAR parameters: anything you can
do with a VAR parameter, you can do with explicit pointers.

I think that these two increment procedures will be (more or less?) equivalent:


type
  intpointer = ^integer;

procedure increment(var n: integer);
  begin
    n := n + 1
  end;

procedure increment2(p: intpointer);
  begin
    p^ := p^ + 1
  end;

var
  a: integer;
  b: integer;
begin
  a := 99;
  increment(a);
  writeln(a);  {will print 100}
  b := 99;
  increment2(@b);
  writeln(b);  {will print 100}
end.



If there's a difference, its a subtle one which I haven't found in a short
amount of testing.



-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list