On 22/06/2013 03:01, I wrote:
On 22/06/2013 02:15, Rick Johnson wrote:
[...]

This is what should happen:

     py> def foo(arg=[]):
     ...     arg.append(1)
     ...     print(arg)
     ...
     py> foo()
     [1]
     py> foo()
     [1]
     py> foo()
     [1]

Yes, Yes, YES! That is intuitive! That is sane! Now, what if
we pass a reference to a mutable object? What then. Well, let's
see:

     py> lst = range(5)
     py> lst
     [0, 1, 2, 3, 4]
     py> def foo(arg=lst):
     ...     arg.append(1)
     ...     print(arg)
     ...
     py> foo()
     [0, 1, 2, 3, 4, 1]
     py> foo()
     [0, 1, 2, 3, 4, 1, 1]

That's fine. Because the object was already created OUTSIDE
the subroutine. So therefore, modifications to the mutable
are not breaking the fundamental of statelessness INSIDE
subroutines. The modification is merely a side effect, and
the subroutine is unconcerned with anything that exists
beyond it's own scope.

IS ALL THIS REGISTERING YET? DO YOU UNDERSTAND?

No, I don't. These two special cases are not sufficient for me to
determine what semantics you are proposing for the general case. For
example, what happens in the second example if lst is rebound? Does the
default stay the same or does it change to the new value of lst? What
about if you pass a call as a default argument, and then subsequently
change the behaviour of the callable? Does the argument get re-evaluated
every time foo() is called, or is the argument guaranteed to be the same
every time? If the latter, what happens if the arguments type is
modified (e.g. by changing one of its class attributes)? What about
defining functions dynamically, with default arguments that are only
known at runtime? Is there any way to avoid the second type of behaviour
in this case? If so, how? If not, isn't that likely to prove at least as
big a gotcha to people who don't know the rules of RickPy as the problem
you're trying to solve?

Since you haven't answered this, allow me to suggest something. One thing that a language could do is treat default arguments as mini function definitions with their own scope, which would be the same as the scope of the function itself but without the function's arguments. In other words, in this alternative version of Python, the following

>>> def f(x = <expression>):
...    <stuff>

would be equivalent, in actual Python, to this:

>>> default = lambda: <expression>
>>> sentinel = object()
>>> def f(x = sentinel):
...    if x is sentinel:
...        x = default()
...    <stuff>

That would be something that could be implemented, and as far as I can tell it's consistent with the examples you've given of how you would like Python to work. Is this indeed the kind of thing you have in mind?

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to