La alternativa sería bastante pesada: almacenar "valores de argumento predeterminados" en el objeto de función como "thunks" de código para ejecutar una y otra vez cada vez que se invoca la función sin un valor especificado para ese argumento - y haría mucho más difícil obtener un enlace anticipado (vinculante en el momento de la definición), que a menudo es lo que desea. Por ejemplo, en Python, ya que existe:
def ack(m, n, _memo={}):
key = m, n
if key not in _memo:
if m==0: v = n + 1
elif n==0: v = ack(m-1, 1)
else: v = ack(m-1, ack(m, n-1))
_memo[key] = v
return _memo[key]
... escribiendo una función memoized como el de arriba es una tarea muy elemental.Del mismo modo:
for i in range(len(buttons)):
buttons[i].onclick(lambda i=i: say('button %s', i))
... la sencilla i=i
, basándose en el (tiempo de definición) de enlace temprano de los valores por defecto arg, es una forma trivial simple para obtener el enlace anticipado. Entonces, la regla actual es simple, directa, y le permite hacer todo lo que quiera de una manera extremadamente fácil de explicar y comprender: si desea vincular tarde el valor de una expresión, evalúe esa expresión en el cuerpo de la función; si desea una vinculación anticipada, evalúela como el valor predeterminado de una arg.
La alternativa, forzando el encuadernado tardío para ambas situaciones, no ofrecería esta flexibilidad, y le obligaría a pasar por aros (como envolver su función en una fábrica de cierre) cada vez que necesitara un encuadernado temprano, como en el ejemplo anterior ejemplos: una regla hipotética de diseño (más allá de los "invisibles" de generación y evaluación repetida de thunks por todas partes) forzó al programador a repetir más peso pesado.
En otras palabras, "Debería haber una, y preferiblemente solo una, forma obvia de hacerlo [1]": cuando desea la vinculación tardía, ya existe una forma perfectamente obvia de lograrlo (ya que todas las funciones el código solo se ejecuta en el momento de la llamada, obviamente, todo lo que se evalúe allí está retrasado); tener una evaluación por defecto de arg produce una vinculación anticipada que le proporciona una forma obvia de lograr un enlace anticipado también (¡más! -) en lugar de dar DOS formas obvias de obtener un enlace tardío y ninguna forma obvia de obtener un enlace anticipado (¡un menos! -).
[1]: "Aunque tal vez no sea obvio al principio a menos que sea holandés".
Mi conjetura sería el rendimiento. Imagínese reevaluar cada vez que se llame a una función si se llama 15 millones de veces al día. –