On 05/06/2015 00:13, Steven D'Aprano wrote:
On Fri, 5 Jun 2015 06:52 am, BartC wrote:

On 04/06/2015 18:11, Steven D'Aprano wrote:

If there is
any language where assignment uses one style and argument passing always
uses another, I've never come across it.

My language does that. I'd be very surprised if it was the only one in
existence that does so.

I would be. That means that

func(x)

and

tmp = x
func(tmp)

behave differently,

Not as far as func() is concerned. But overall there is a difference because now tmp contains a copy of x. (Also, if x contains a list for example, func() can modify the copy in tmp, not in x. But this shouldn't be surprised because the code is different!)

 and that would be very surprising to me (and, I think,
most people).

Assignments involve a deep copy. Argument passing is something
in-between by-value and by-reference (depending also on the type of data
involved).

When you say "something in-between ...", do you mean pass by sharing?

No, it's a rather untidy mechanism which is not intended to be used when a parameter is modified (mutated), because the information passed is incomplete. But for read-access, or local assignment is used within the function, it works as expected.


There is a also an actual by-reference mode (where a pointer
is passed).

Passing a pointer is not necessarily by reference. Pass by sharing also uses
a pointer.

This can get tricky to explain. If variables (if you forgive me that term) are implemented actually as pointers, then when you pass that variable to a function, a copy of the pointer it contains is pushed (I think this is how CPython works).

In that case, it is not passed by reference, even though a pointer is used. Because the pointer doesn't point /at/ the variable, but with it. So if the variable contains a List, its pointer points to the list, and the function parameter points at the same list; it can change the list, but it can't make the variable point to something else.

When I use pass-by-reference then, regardless of whether variables already make use of pointers, I need to construct an extra pointer that points /at/ the variable (and box it in my case).

(Example of how I think CPython works:

 def fn():
    a = 5622
    b = [10,20,30]

For this purpose, a and b are locals, and they are allocated on some sort of stack, which gives them one pointer each. After those assignments, they might contain:

  a (pointer 1003)  ->    1003: [int 5622 ....]
  b (pointer 1007)  ->    1007: [list ........]

Now the following is executed:

    fn2(a)

A copy of a, (pointer 1003), is pushed, which points to the int. These are immutable anyway. It is impossible (AFAIK) to make a contain something else, such as a string, from outside fn().

The language could be extended:

    x = &a

x might now be:

  x (pointer 1012)  ->    1012: [Ref (pointer 1003)]

Now it is possible to call fn2(x), and inside fn2, some dereferencing is done (using explicit pointer ops, C-style):

     *x = "XYZ"        # this will change a)

--
Bartc
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to