RE Python non segue questo principio. In generale, segue il principio. Esempio di base:
>>> x = ['foo']
>>> x
['foo']
>>> x = (lambda: ['foo'])()
>>> x
['foo']
Tuttavia, Python definisce le espressioni e le dichiarazioni separatamente. Poiché i if
rami, i while
cicli, i compiti distruttivi e le altre dichiarazioni non possono essere affatto utilizzati nelle lambda
espressioni, la lettera del principio di Tennent non si applica a loro. Anche così, limitarsi a usare solo espressioni Python produce ancora un sistema completo di Turing. Quindi non vedo questo come una violazione del principio; o meglio, se viola il principio, allora nessun linguaggio che definisce le dichiarazioni e le espressioni separatamente può eventualmente conformarsi al principio.
Inoltre, se il corpo lambda
dell'espressione stava acquisendo una traccia dello stack o eseguiva altre introspezioni nella VM, ciò potrebbe causare differenze. Ma secondo me questo non dovrebbe essere considerato una violazione. Se expr
e (lambda: expr)()
necessariamente compilare con lo stesso bytecode, allora il principio riguarda davvero i compilatori e non la semantica; ma se possono compilare in bytecode diverso, non dovremmo aspettarci che lo stato della VM sia identico in ogni caso.
Una sorpresa può essere riscontrata usando la sintassi della comprensione, anche se credo che questa non sia una violazione del principio di Tennent. Esempio:
>>> [x for x in xrange(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [f() for f in [lambda: x for x in xrange(10)]] # surprise!
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
>>> # application of Tennent principle to first expression
... [(lambda: x)() for x in xrange(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [f() for f in [(lambda x: lambda: x)(x) for x in xrange(10)]] # force-rebind x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> map(lambda f:f(), map(lambda x: lambda: x, xrange(10))) # no issue with this form
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
La sorpresa è il risultato di come sono definite le comprensioni dell'elenco. La comprensione "sorpresa" sopra è equivalente a questo codice:
>>> result = []
>>> for x in xrange(10):
... # the same, mutable, variable x is used each time
... result.append(lambda: x)
...
>>> r2 = []
>>> for f in result:
... r2.append(f())
...
>>> r2
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
Vista in questo modo, la comprensione della "sorpresa" sopra è meno sorprendente, e non una violazione del principio di Tennent.