a question regarding call-by-reference

Bengt Richter bokr at oz.net
Tue Feb 7 13:35:46 EST 2006


On 6 Feb 2006 10:21:45 -0800, "enjoying the view" <pparkkin at gmail.com> wrote:

>I am working on a school project, trying to build a simple RPC stub
>generator. The idea is that the generator takes a normal python file
>with functions defined in it and produces a client and server stub. The
>client stub has the same functions defined, but they just connect to
>the server and ask it to call the desired functions. The server stub is
>a server listening for incoming requests and dispatching them to the
>appropriate functions and sending back the results. Extremely simple
>and I've gotten it to mostly work, but I have one problem:
>call-by-reference parameters. An example:
>
>A function like this:
>def sum(a, b):
>  return a + b
>
>would yield a client stub like this (simplified):
>def sum(a, b):
>   send_message({'funcname': 'sum', 'args': (a, b)})
>   result = receive_message()
>   return result
>
>Now, this works just fine. I get problems when I try to do something
>like this:
>def add_elm(list):
>   list.append('elm')
>   return
>
>Imported normally this would work fine. The list given as a parameter
>would be one element larger. But when the stubs are generated, the
>function doesn't return anything and the list is appended in the server
>and the client-side list is left untouched. At first I thought the
>solution was easy, just return the changed parameters and place them in
>the parameter variables in the client stub:
>def add_elm(list):
>   send_message({'funcname': 'add_elm', 'args': (list)})
>   response = receive_message()
if the response contains an updated list, you can update the content
of the add_elm caller's list by slice assignment, e.g.,
    list[:] = response.get(<however you get the updated list>')

But you are in really tricky territory here I think. There is any number
of ways to mutate objects via function argument reference. Not just
if they're lists. And lists can be deeply nested, so you could be sending
deep copies of lists across a network, which could involve most of your memory
even if the first level has only a few elements. And if there are side effects besides
the direct mutations, you have additional problems. What if a function accesses
arg.prop and that's a property that keeps count or otherwise tracks instances of something?

The totally general solution is probably impossible. So if I were you I would go back to
the specifier of this problem and negotiate some severe restrictions on assumptions
about arguments (maybe just outlaw direct mutation and access side effects ;-)

>   (list) = response.get('args')
>   return response.get('result')
>
>The problem is, this doesn't work. The original list doesn't point to
>the changed list. I have been trying to figure this out and it seems
>that if I just assign to the list variable it just modifies the local
>(to the function) name space, and that those changes aren't reflected
>in the list in the original name space.
>
>I believe there are some ways around this, but I haven't found one that
>would not require any special handling in either the code calling the
>client stub or the original functions. I want to maintain transparency.
>
>etv
>
Good luck ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list