What is a function parameter =[] for?

Chris Angelico rosuav at gmail.com
Thu Nov 19 14:19:06 EST 2015


On Fri, Nov 20, 2015 at 5:19 AM, BartC <bc at freeuk.com> wrote:
> Yes. In the languages I create, pretty much everything is mutable, provided
> it can supply an l-value. Constructs such as those for empty lists ([] in
> Python, () in mine) aren't l-values.
>
> But it doesn't apply default values. The language is very different however,
> because the byte-code compiler always has full knowledge of functions that
> are called directly. Then it knows when an argument is omitted, and can
> simply substitute the expression used as the default.

In other words, your language uses late binding by default. That's
fine; it's a design choice that you've made one way and Python's made
the other way. It's on par with design choices like whether adding a
string and an integer implicitly stringifies the int, or raises an
error. I know several good languages that have taken each of those
choices.

But every choice has consequences. Steven gave you a few examples of
the consequences of late-binding default arguments. For example, can
you translate this into (one of) your language(s), and explain the
semantics of the late binding?

# scope 1: can be a module, an inner function, whatever
y = 42
def func(x=y):
    return x
def change_y():
    global y # affect the one in this scope
    y = 28

# scope 2: another module/function/etc
from scope1 import func # gain access, however that's done

change_y()
y = 7
func()


Should this return 7, 28, or 42? Early binding demands 42, which is
nice and simple: you don't need to look anywhere outside the
function's own definition to grok its defaults. The default is stable
(it won't change from one run to another - it'll always be the same
object). Scope-recognizing late binding would use 28; it re-evaluates
the expression 'y' in its original scope. This one makes the most
sense to me, of all late-bind semantics; it also happens to be the
same semantics as you get if you do the classic "if x is None: x=y"
late-bind in Python, modulo the effect of the nested scope. But you're
saying that it "simply substitute[s] the expression", which would mean
that "func()" is exactly the same as "func(y)". A function default
argument is therefore able to STEAL STUFF FROM THE CALLER'S SCOPE.
Sorry for shouting, but if that ain't bizarre, I don't know what is.

ChrisA



More information about the Python-list mailing list