Was ist die gute Erklärung für Tennents Korrespondenzprinzip?

21

Ich bemühte mich zu verstehen, worum es bei diesem Prinzip geht und warum es für das Sprachdesign so wichtig ist.

Grundsätzlich heißt es, dass für jeden Ausdruck exprin der Sprache genau das Gleiche gelten sollte wie für dieses Konstrukt:

(function () { return expr; })()

Ich habe auch gehört, dass Ruby diesem Prinzip folgt, während Python dies nicht tut. Ich verstehe nicht, warum das stimmt oder ob es überhaupt stimmt.

Andrew
quelle
3
Ich kann nicht verstehen, warum es nicht zum Thema gehört. Kann mir das jemand erklären?
Andrew
3
Es gibt ein paar Probleme; Ich habe es aufgearbeitet und sende es an Programmierer, wo Diskussionen wie diese etwas willkommener sind.
Ripped Off
1
Ruby hält sich nicht an dieses Prinzip: Angenommen, es exprwird der aktuelle Stack-Trace abgerufen.
Landei

Antworten:

18

Ich habe noch nie zuvor von "Tennents Korrespondenzprinzip" gehört, und noch weniger davon, dass es für das Sprachdesign wichtig ist. Das googeln der Ausdrücke scheint alles zu einem Neal Gafter-Blog von 2006 zu führen, in dem festgelegt ist, was er denkt, und wie er denkt, dass es auch für Schließungen gelten sollte. Und die meisten anderen in Foren scheinen sich auf Gafters Eintrag zu beziehen.

Hier ist jedoch eine Erwähnung des "TCP" von Douglas Crockford (ein Name, den ich kenne und dem ich vertraue): http://java.sys-con.com/node/793338/ . Teils

Es gibt einige Dinge, die auf diese Weise nicht eingeschlossen werden können, z. B. return-Anweisungen und break-Anweisungen, die die Befürworter von Tennents Correspondence Principle (oder TCP) als Symptom für einen schlechten Geruch bezeichnen. Yow! Sprachdesign ist schon schwierig genug, ohne mit olfaktorischen Halluzinationen fertig zu werden. Um das Problem besser zu verstehen, kaufte ich mir ein Exemplar von Tennents 1981em Buch Principles of Programming Languages.

Es stellt sich heraus, dass das Korrespondenzprinzip beschreibend und nicht vorschreibend ist . Er analysiert damit die (inzwischen vergessene) Programmiersprache Pascal und zeigt eine Korrespondenz zwischen Variablendefinitionen und Prozedurparametern. Tennent sieht in der mangelnden Übereinstimmung der Rückmeldungen kein Problem .

Daher scheint der Name "Tennent's Correspondence Principle" missbraucht zu werden, und was auch immer Neal spricht, sollte möglicherweise "Gafter's Imagined and Possibly Generalized TCP" heißen ... oder so. Auf jeden Fall nicht genug, um sich hinter einem vergriffenen Vorhang zu verstecken

Nas Banov
quelle
1
+1 für "Gafters imaginiertes und möglicherweise verallgemeinertes TCP"
jcora
9

Ich sehe dies als Teil einer allgemeinen Regel, dass eine gut gestaltete Sprache das tut, was ein Programmierer natürlich erwarten würde. Wenn ich einen Codeblock habe, den ich in einen Closure umgestalten möchte, und diesen Block mit der entsprechenden Syntax umhülle, ohne wirklich über die einzelnen Codezeilen nachzudenken, erwarte ich, dass dieser Block im Closure dasselbe tut wie er tat Inline. Wenn in einigen Anweisungen das Schlüsselwort "this" (möglicherweise implizit) verwendet wird und die Sprache "this" innerhalb des Abschlusses als Verweis auf eine anonyme Klasse zur Darstellung verwendet, und nicht auf die Klasse, die die Methode definiert, die den Abschluss definiert, dann auf die Bedeutung von Diese Anweisungen haben sich geändert, mein Codeblock entspricht nicht mehr meiner Meinung und ich muss einen Fehler aufspüren und herausfinden, wie ich meinen Code ändern kann, damit er im Closure funktioniert.

Das Problem könnte auch mit einer IDE mit intelligenten Refactoring-Tools behoben werden, die Abschlüsse extrahieren, potenzielle Probleme erkennen und den extrahierten Code sogar automatisch anpassen können, um die Probleme zu lösen.

JGWeissman
quelle
3

Claus Reinke: zu Tennents "Sprachgestaltung nach semantischen Prinzipien"
Interessante Interpretation der Prinzipien:
"Korrespondenz ist das Prinzip, das man so sagen kann

let(this=obj, x=5) { .. }  

und

((function(x) { .. }).call(obj,5))  

sollten gleichwertig sein und alles, was wir in formalen Parameterlisten tun können, sollten wir auch in Deklarationen tun können und umgekehrt. "[siehe auch Reinke unten]

RD Tennent: Sprachentwurfsmethoden basierend auf semantischen Prinzipien
"Zwei Sprachentwurfsmethoden basierend auf Prinzipien, die aus dem denotationalen Ansatz der Programmiersprachensemantik abgeleitet sind, werden durch eine Anwendung auf die Sprache Pascal beschrieben und illustriert. Die Prinzipien sind zum einen die Korrespondenz zwischen parametrischen und deklarative Mechanismen und zweitens ein Abstraktionsprinzip für Programmiersprachen, das an die Mengenlehre angepasst ist. Mehrere nützliche Erweiterungen und Verallgemeinerungen von Pascal ergeben sich aus der Anwendung dieser Prinzipien, einschließlich einer Lösung für das Array-Parameter-Problem und einer Modularisierungsmöglichkeit. "

Claus Reinke: "Über funktionale Programmierung, Sprachgestaltung und Beharrlichkeit" bei Haskell

Kris
quelle
Claus Reinke: "Über funktionale Programmierung, Sprachgestaltung und Beharrlichkeit" auf Haskell unter community.haskell.org/~claus/publications/fpldp.html
Kris
2

Um die Frage zu beantworten, warum Tennents CP für das Sprachdesign so wichtig ist, möchte ich Neal Gafter zitieren :

Die Prinzipien von Tennent sind sehr wirkungsvoll, da Verstöße in der Sprache als Fehler, Unregelmäßigkeiten, unnötige Einschränkungen, unerwartete Interaktionen oder Komplikationen usw. angezeigt werden.

Jeder Verstoß gegen TCP wird in Zukunft wahrscheinlich einige Programmierer verletzen, wenn er davon ausgeht, dass Closures wie Nicht-Closure-Code funktionieren, dies jedoch bei einem Verstoß gegen TCP nicht der Fall ist.

Thiton
quelle
1

RE Python folgt diesem Prinzip nicht. Im Allgemeinen folgt es dem Prinzip. Einfaches Beispiel:

>>> x = ['foo']
>>> x
['foo']
>>> x = (lambda: ['foo'])()
>>> x
['foo']

Python definiert jedoch Ausdrücke und Anweisungen separat. Da ifVerzweigungen, whileSchleifen, destruktive Zuweisungen und andere Anweisungen in lambdaAusdrücken überhaupt nicht verwendet werden können , gilt der Buchstabe des Tennent-Prinzips nicht für sie. Selbst wenn Sie sich darauf beschränken, nur Python-Ausdrücke zu verwenden, erhalten Sie immer noch ein Turing-Gesamtsystem. Ich sehe das also nicht als Verstoß gegen das Prinzip; oder vielmehr, wenn es gegen das Prinzip verstößt, kann möglicherweise keine Sprache, die Aussagen und Ausdrücke separat definiert, dem Prinzip entsprechen.

Auch wenn der Körper des lambda Ausdrucks eine Stapelverfolgung aufzeichnet oder eine andere Introspektion in der VM durchführt, kann dies zu Unterschieden führen. Meiner Meinung nach sollte dies jedoch nicht als Verstoß gewertet werden. Wenn exprund (lambda: expr)() notwendigerweise zu demselben Bytecode kompiliert wird, dann betrifft das Prinzip wirklich Compiler, nicht Semantik; Wenn sie sich jedoch zu einem anderen Bytecode kompilieren lassen, sollten wir nicht erwarten, dass der VM-Status in jedem Fall identisch ist.

Eine Überraschung ist bei der Verwendung der Verständnissyntax zu erwarten, auch wenn dies meiner Meinung nach keine Verletzung des Tennent-Prinzips darstellt. Beispiel:

>>> [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]

Die Überraschung ist das Ergebnis der Definition des Listenverständnisses. Das obige "Überraschungs" -Verständnis entspricht diesem Code:

>>> 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]

So gesehen ist das obige "Überraschungs" -Verständnis weniger überraschend und keine Verletzung des Tennent-Prinzips.

wberry
quelle