Python to C Converter

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

@BlackJack: Kann ich nachvollziehen, JS hat ein paar Designfehler ¹ aber Crockford listed m.E. ein paar sehr gute Workarounds auf. (wobei ich sein Buch nicht mag)

LISP Macros wären dafür schön.... Aber zugegeben letztendlich braucht man eine Metasprache die in JS umgesetzt wird.

Minimalismus hat halt seine Nachteile, aber der Vorteil ist, dass es jetzt wohl die Plattformmäßig die meistverbreitete Sprache ist und sowas wie ein JIT-Compiler wie es scheint viel einfacher umzusetzen ist.

Ich brauch mir z.B. für kleine Anwendungen auch keinen Kopp zu machen ob mein Smartphone Android oder IPhone OS hat, DHTML kann ich heutzutage fast überall fahren.

OTOH gibts Sachen die in JS konsequenter umgesetzt sind als in Python, z.B. keine eingeschränkten Lambdas oder richtige Closures.

Das dich die "Flexibilität" des OO-Models nervt erklärt sich wohl auch aus deiner Python Herkunft, wenn man von Perl kommt, wie ich ist man TIMTOWTDI gewöhnt...roter Faden ist dann halt Guido's World.

1) konkret es fehlen einfach noch 2-3 Kommandos/Flags, z.B. damit man einfach durch ein Hash iterieren kann OHNE die gerbten Methoden aufzulisten.
Zuletzt geändert von LanX am Freitag 23. Juli 2010, 16:25, insgesamt 1-mal geändert.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

BlackJack hat geschrieben:Benutze in einem Projekt 3 grössere Bibliotheken und Du hast drei verschiedene Vererbungsmodelle im Programm. Plus dem Eigenen vielleicht noch.
Deswegen nutzt man ein Framework wie jQuery und wenn man mehr braucht nutzt man Plugins.
lunar

@LanX: "Flexibilität" ist auch in Programmen kein Selbstzweck, sondern nur gut, wenn sie einem Zweck dient. Bei einem Vererbungsmechanismus ist das nicht unbedingt sinnvoll.

@DasIch: Das funktioniert nur, wenn man absolute Kontrolle über Umgebung und Projekt hat. Und wie oft ist das in der Realität schon der Fall?
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

lunar hat geschrieben:@LanX: "Flexibilität" ist auch in Programmen kein Selbstzweck, sondern nur gut, wenn sie einem Zweck dient. Bei einem Vererbungsmechanismus ist das nicht unbedingt sinnvoll.
@lunar: Prototypische Vererbung ist ziemlich simpel und klar definiert, alles anderen Vererbungsmechanismen sind von Modulautoren draufgesattelt, die es gerne wie zu Hause haben wollen (meistens ist Java=Daheim)

Auch kann man auch mit Closures in JS viel weiter kommen, wo man in Python zu umständlicherer OOP gezwungen wird.

Ist das dann noch ein NPOV? Ich meine, weil nicht py-mäßig ist, ist es nicht unbedingt schlechter...

Aber hier prallen IMHO auch die unterschiedlichen Paradigmen von Perlern und Pythonistas aufeinander...TIMTOWTDI.
problembär

LanX hat geschrieben:ich kenne das Thema aus Perl boards, das Hauptproblem ist die dynamische Typisierung von Scriptsprachen.
Ja:

http://www.perl.com/pub/2001/06/27/ctoperl.html

Dürfte für Python entsprechend gelten.
BlackJack

@LanX: Das JavaScript die meistverbreitete Sprache ist, halte ich für ein Gerücht -- jedenfalls wenn man da nicht noch Einschränkungen bei dieser Annahme macht. Überleg einfach mal wieviel mehr Embedded-Systeme in allen möglichen "intelligenten" Geräten -- von der Waschmaschine bis zum Auto stecken -- im Gegensatz zu den "paar" Rechnern mit Web-Browsern. ;-)

Python hat richtige Closures. Seit ``nonlocal`` auch welche, die semantisch wie bei JavaScript benutzt werden können, aber auch ohne sind das richtige Closures.

Die "Flexibilität" des OO-Models nervt mich nicht wegen der Python-"Vorbelastung" sondern weil ich sowohl bei Scheme als auch bei JavaScript schon die "Freuden" von mehreren Modellen in einem Projekt "geniessen" durfte. Das macht keinen Spass. Zumal das was man so im allgemeinen als den "vorgesehenen" Weg präsentiert bekommt 1. syntaktisch ziemlich blöd aussieht und 2. mit dem "leeren" Exemplar der Basisklasse als Prototyp IMHO ziemlich hässlich ist, weil man den Konstruktor ja so schreiben muss, dass man ihn auch komplett ohne Argumente aufrufen kann.

Schöne und einfache prototypische Vererbung hat zum Beispiel Io. Dagegen sieht der JavaScript-Krampf hässlich wie die Nacht aus.

JavaScript hat ein paar nette Grundgedanken, aber wenn ich das nächste mal damit etwas machen muss, werde ich das wohl über CoffeeScript in Angriff nehmen. Und das nicht nur weil die Sprache ein Vererbungssystem vorgibt (mit denen von Bibliotheken muss man sich im Ernstfall ja trotzdem rumschlagen).
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

LanX hat geschrieben:Ja aber JS ist extrem kompact und erweiterbar, dass macht die Implementierung und Optimierung auch so einfach.

Laut WP ist PyPy nicht wirklich schneller als CPython, während V8 abgeht wie ein geöltes Zäpfchen.
Wie schon erwähnt, funktioniert der JIT inzwischen soweit, dass PyPy fast immer deutlich schneller als CPython ist. Aktuelle Zahlen: http://speed.pypy.org/
Darii hat geschrieben:JS find ich persönlich eher abstoßend.
Geschmacksache, ich sattle mir immer drauf was mir fehlt. Prototypische Vererbung machts möglich...
Das ist das Problem. Jede umfangreichere Bibliothek implementiert eigene Vererbungsmechanismen. D.h. man darf die Sprache für jede Bibliothek neu lernen. Und wenn schon prototypenbasiert dann bitte Self.
Darii hat geschrieben: Der Sprache fehlt der rote Faden.
Roter Faden = "There is only Guido's way to do it" ??? ;-)
Würde nicht schaden.

Was ich hauptsächlich störend finde sind die seltsame Syntax zur Definition von Objekten, die dieses eigentlich völlig überflüssige new-Schlüsselwort erfordert. Das seltsame this, auf das man sich nicht verlassen kann (var self = this *hust*). Und die umständliche Scoping-Regel, der man zu verdanken hat, dass man vor praktisch jede Variable var schreiben muss. Die Zahl der Prototypen ist natürlich auch nur auf einen beschränkt. Und die Möglichkeit ein Programm gescheit in mehrere Dateien aufzuteilen und somit etwas zu strukturieren fehlt auch völlig. Da braucht man dann wieder zusätzliche Software (sprich: Präprozessoren).
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

BlackJack hat geschrieben: 2. mit dem "leeren" Exemplar der Basisklasse als Prototyp IMHO ziemlich hässlich ist, weil man den Konstruktor ja so schreiben muss, dass man ihn auch komplett ohne Argumente aufrufen kann.
Musst du in Python bei Mehrfachvererbung eigentlich auch machen, sonst knallt u.U. super irgendwo.
BlackJack

@Darii: Ich verwende weder Mehrfachvererbung noch `super()`. Höchstens mal "Mixin"-Klassen, aber das auch sehr selten.
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

BlackJack hat geschrieben: Überleg einfach mal wieviel mehr Embedded-Systeme in allen möglichen "intelligenten" Geräten -- von der Waschmaschine bis zum Auto stecken -- im Gegensatz zu den "paar" Rechnern mit Web-Browsern. ;-)
Tatsächlich! Nächstes mal wenn ich mich auf meiner Waschmaschine oder Auto einlogge werde ich besser drauf achten in welcher Sprache ich progge... ;-)
BlackJack hat geschrieben:Python hat richtige Closures. Seit ``nonlocal`` auch welche, die semantisch wie bei JavaScript benutzt werden können, aber auch ohne sind das richtige Closures.
Soso, und mit nonlocal werdens dann "richtigere" Closures ... :-P
BlackJack hat geschrieben:Die "Flexibilität" des OO-Models nervt mich nicht wegen der Python-"Vorbelastung" sondern weil ich sowohl bei Scheme als auch bei JavaScript schon die "Freuden" von mehreren Modellen in einem Projekt "geniessen" durfte.

Es hat sich leider (noch) kein einheitliches Best Practice durchgesetzt, das hat viele Gründe, siehe The World's Most Misunderstood Programming Language

Meine Aussage war aber dass JS trotzdem einfach zu erweitern ist und gleichzeitig der Kern trotzdem wg seiner Kompaktheit einfach zu implementieren und zu tunen ist.
BlackJack hat geschrieben: Das macht keinen Spass.
Also die Notwendigkeit eines Hash-Objektes in Prototype.js finde ich in der Tat verwirrend. Es ist halt leider Designfehler dass man bei vererbten Methoden keine Spezialflags setzen kann - wie z.B. mit "isEnumerable" vorhanden - setzen kann.

Aber, hei ...andere Sprachen verzichten dafür darauf rechtzeitig "nonlocal" einzuführen, und vertrösten auf die nächste Hauptversion... shit happens :)

BlackJack hat geschrieben: Zumal das was man so im allgemeinen als den "vorgesehenen" Weg präsentiert bekommt 1. syntaktisch ziemlich blöd aussieht und 2. mit dem "leeren" Exemplar der Basisklasse als Prototyp IMHO ziemlich hässlich ist, weil man den Konstruktor ja so schreiben muss, dass man ihn auch komplett ohne Argumente aufrufen kann.

Schöne und einfache prototypische Vererbung hat zum Beispiel Io. Dagegen sieht der JavaScript-Krampf hässlich wie die Nacht aus.
Auch hier verweise ich gerne auf Crockford http://javascript.crockford.com/prototypal.html.

Io kenne ich nicht aktiv... Aber Interessant, eine Sprache die trotz M-Expressions Macros beherrscht hört sich tatsächlich faszinierend an.

Allerdings wo komme ich damit in Berührung? Etwa in meiner Waschmaschine... ;-)
BlackJack hat geschrieben:JavaScript hat ein paar nette Grundgedanken, aber wenn ich das nächste mal damit etwas machen muss, werde ich das wohl über CoffeeScript in Angriff nehmen.
Interessant http://jashkenas.github.com/coffee-script/ ....

Meine Vision geht aber eher dahin ein zurechtgestutztes Perl einzusetzen, >95% der JS Semantik (inkl Objektmodell) ließe sich bereits heute 1:1 abbilden.

Die restlichen 5% sind das -ähm - unorthodoxe scopingverhalten von var und Details bei der Typkonversionen...

In Perl hätte ich dann dank expliziten concat operators auch explizit die Möglichkeit zwischen 1+0 und "1"+"0" zu unterscheiden.

PS: Kann man in diesem PHP Board eigentlich den Teilthread über JS absplitten, mit C hats ja nur noch bedingt zu tun...
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

Darii hat geschrieben: Was ich hauptsächlich störend finde sind die seltsame Syntax zur Definition von Objekten, die dieses eigentlich völlig überflüssige new-Schlüsselwort erfordert.
ja ... das "new" hatte wohl Marketinggründe, wie die umbenennung von in JAVAscript.
Darii hat geschrieben: Das seltsame this, auf das man sich nicht verlassen kann (var self = this *hust*).
ich kann dir nicht folgen... Beispiel?
Darii hat geschrieben: Und die umständliche Scoping-Regel, der man zu verdanken hat, dass man vor praktisch jede Variable var schreiben muss.
hä??? ... gibts außer Python eine andere (nichtakademische) Sprache die per default localisiert und wo man explizit "nonlocal"-isiseren muss (wenn man denn kann)?

"var" ist nervig weil es für den ganzen Scope - also auch vorhergehenden Code - gilt.¹
Deswegen bemängelt Crockfords JS-Lint es auch wenn du die var-Deklarationen nicht am Funktionsanfang machst.
Darii hat geschrieben: Die Zahl der Prototypen ist natürlich auch nur auf einen beschränkt.
Das ist IMHO ein fettes Plus! Ich bevorzuge - schon aus Designgründen - Mixins. Die Nützlichkeit der Mehrfachvererbung ist m.E. ein Mythos.
Darii hat geschrieben: Und die Möglichkeit ein Programm gescheit in mehrere Dateien aufzuteilen und somit etwas zu strukturieren fehlt auch völlig. Da braucht man dann wieder zusätzliche Software (sprich: Präprozessoren).
Doch Packaging bekommt man schon ohne Präprozessoren hin, aber auch hier gibts leider keine akzeptierte Best Practice.

1) ich bin mir nicht ganz sicher was Python macht, wenn ich eine neue Variable binde ...gleich mal testen...
BlackJack

@LanX: Es wird sich wohl auch keine einheitliche Best Practice durchsetzen. Das ist eben der Nachteil bei der Freiheit an der Stelle.

Ich sehe ``nonlocal`` nicht als essentiell wichtig an. Python hat Klassen, man bekommt da also nichts, was man vorher nicht auch relativ einfach ausdrücken konnte. Klassen sind ein wichtiger Bestandteil von Python und nichts exotisches. Wenn man sie braucht, sollte man sie auch verwenden.

Crockford bastelt mit der `Object.create()`-Funktion `clone` aus Io nach. Der Punkt ist, dass man so etwas Kleines aber Essentielles nicht selber machen sollen müsste. Denn Crockford macht das so und nennt das `create`. Der nächste macht das gleiche und nennt es aber anders. Ein dritter macht etwas leicht verschiedenes, nennt es aber auch `create` und pappt es an das globale `Object`. Und dann versuch mal Code von diesen drei Programmieren in einem Programm zu verwenden.

Nichts gegen Freiheit, aber bei solch grundlegenden Dingen sollte von den Sprachentwicklern mindestens ein Weg fertig und ohne Boilerplate funktionierend angeboten werden. Wer was anderes will, soll ja ruhig die Möglichkeit haben. Bei Io kann man sich auch andere Semantiken basteln.

Ich persönlich mag bei JavaScript am liebsten das Idiom was Crockford "functional inheritance" nennt. :-)
BlackJack

@LanX: Ich verstehe Deine Anmerkung zum Scope nicht wirklich. Ohne ``var`` sind Variablen in JavaScript *global* und zwar so *richtig* global. Das ist doof weil in 99% der Fälle nicht das was man will. Und dass sich das ``var`` egal wo es steht auf die Funktion und nicht den Block besteht, ist die nächste Überraschung.

Beispiel für's `this` sind Methoden die man rumreicht und die vielleicht irgendwo in anderen Bibliotheken an ein Objekt gebunden werden, weshalb man das `this` selbst vorher in einem Closure "festnageln" muss, weil es sonst bei der Ausführung nicht an das Objekt gebunden ist, von dem die Methode ursprünglich mal kam. Bin ich auch erstmal mit auf die Schnauze gefallen.

Zum Packaging bringt CommonJS ja vielleicht eine Vereinheitlichung.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

An paar Anmerkungen: Es ist Mythos, dass fehlende statische Typen zwangsläufig langsamere Programme ergeben. Da gibt es ein Paper aus dem Self-Projekt so ca. 1995, das ich aber zu faul bin, jetzt herauszusuchen, welches das Gegenteil zeigt. Dynamisch typisierte Sprachen sind in der Regel langsamer, weil sie ausdrucksstärker als ihre statisch kompilierenden Brüder sind. So bieten die meisten z.B. korrekte Artithmetik ohne Überlauf ins negative, eine automatische Speicherverwaltung oder ein Modell, wo jeder Datentyp gleichartig (als Objekt) behandelt wird. Mehr Features drücken da natürlich auf die mögliche Maximalgeschwindigkeit.

Ein Python-Programm in ein äquivalentes C-Programm zu übersetzen erfordert letztlich, dass in diesem C-Programm ein kompletter Python-Interpreter vorhanden ist, denn z.B. der exec-Befehl müsste ja funktionieren. Man will also in jedem Fall ein Subset von Python in C übersetzen.

Der andere Ansatz wäre, mit dem semantischen Modell von C zu beginnen, dies in eine Python-Syntax einzupacken und dann zu schauen, welche Features, die C nicht bietet aber Python jetzt noch "billig" hinzuzufügen wären.

Der Autor von Galcon ist auch Autor von tinypy und hat dafür einen Python nach C++ Übersetzer gebaut, damit er Spiele wie Galcon (was AFAIK einen Python-Teil hat oder sogar ganz in Python geschrieben ist) in C++ übersetzen und so einfacher für's iPhone entwickeln kann. So weit ich weiß, ist die Calcon-Version für's iPhone dann aber doch direkt in C++ und/oder Objective-C++ geschrieben worden.

Tinypy könnte aber vielleicht auch so schon für embedded Systeme geeignet sein. Aber auch hier gilt: Das ist kein Python gemäß der von GvR erstellten Spezifikation, sondern etwas, das eine ähnliche Syntax hat und mehr oder weniger nahe bei Python gelegen hat.

Ich hatte man angefangen, einen Übersetzer für ein mit Python-Syntax geschriebenes Java-Programm nach Java zu bauen: http://github.com/sma/dython Damit das funktioniert, braucht man jedoch einen guten Typ-Inferenzer und dazu war ich im May nicht motiviert genug. Statt Java könnte man aber genauso gut auch C-Code erzeugen, müsste dann noch einen GC dazu tun (boehmgc) und ein bisschen Laufzeitbibliothek entwickeln. Ich wollte ja einfach dem Duby^W Mirah-Ansatz folgen und ausschließlich das Laufzeitsystem der Zielsprache einsetzen.

Ich würde übrigens so weit gehen und sagen, JavaScript (ECMAScript 5) kann man prinzipiell schneller ausführen als Python, weil es weniger flexibel ist und weniger Konzepte der Implementierung durchscheinen. Als Beleg würde ich die belang mäßigen (um nicht zu sagen enttäuschenden) Erfolge des Unladen Swallow-Projekts anführen gegenüber dem V8-Projekt und das, obwohl die wirklich wussten, was sie tun und alle State-of-the-Art-Techniken kannten.

Des weiteren würde ich eine Lanze für JavaScript brechen wollen und sagen, dass ich die Sprache nett finde und nur empfehlen kann, Vorurteile abzulegen und sich näher damit zu beschäftigen. Immerhin ist es die am weitesten verbreitetste Sprache und sie wird uns noch viele Jahre erhalten bleiben.

Besser als Lisp (was ich als CommonLisp lesen würde) ist IMHO Scheme, was Reinheit und Klarheit der Konzepte angeht. Diese findet man (bis auf Continuations) auch in JavaScript wieder. Dazu kommt das Objektkonzept von Self, welches sich aus Smalltalk weiterentwickelt hat. Objective-C ist übrigens der Versuch, das Objektmodell von Smalltalk über C zu stülpen. War so eine "das kann doch nicht so schwer sein Idee" von Brad Cox, der 1986 Smalltalk sah, aber lieber C machen wollte und die Idee von Software-Komponenten verfolgte. Der größte Fehler war, die Blöcke zu ignorieren. Kaum 25 Jahre später hat Apple ihn dann korrigiert und eigenmächtig in ihre Version von C, C++ und Objective-C das Konzept von Blöcken integriert. Die selben Blöcke von Smalltalk (traditionell keine Closures wie bei Scheme) machen Ruby übrigens zu einer der mächtigsten Sprachen, was DSLs angeht.

Wo war ich? JavaScript! Ich denke, wo heutzutage C der portable Assembler (wer nicht muss, nutzt diese primitive Sprache doch hoffentlich nicht mehr freiwillig einfach nur so) wird in Zukunft JavaScript im Web-Umfeld diese Rolle übernehmen. 2012, wenn es nach Brendan Eich geht, kommt die nächste EcmaScript-Version, die ein paar weitere Probleme von JS beseitigt, etwa die standardmäßig globalen Variablen oder das Fehlen eines "doesNotUnderstand"-Catchalls. Wie auch immer, CoffeeScript ist ein schönes Beispiel für die JS-ist-portabler-Assembler-für-andere-Sprachen Ansatz.

Lua wäre übrigens anstelle von Python eine IMHO sehr schöne Alternative, wenn es um embedded Systems geht. Gibt es auch einen recht fixen JIT dafür.

Übrigens, Closures sind alles, was man braucht, um Objekte zu realisieren. Daher kann man in Scheme so schön als Fingerübung ein OO-System bauen. Andersherum ginge es auch, ist aber deutlich anstrengender. Wer den Schmerz fühlt, den man hat, wenn man in Java funktional programmieren will, weiß, was ich meine.

Und wer mal "verrückte" (im Sinne von genial) funktionale Programmierung in JavaScript sehen will, schaue sich (fab) (die Klammern gehören zum Produktnamen) (http://github.com/jed/fab) an, ein funktionales Webrahmenwerk für JavaScript.

Noch was: Wer Io mag (und damit eigentlich auch Self mögen müsste) schaue sich mal Ola Binis Ioke an. Das ist eine ziemlich interessante (experimentelle) Weiterentwicklung an.

Stefan
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

LanX hat geschrieben: 1) ich bin mir nicht ganz sicher was Python macht, wenn ich eine neue Variable binde ...gleich mal testen...

Code: Alles auswählen

>>> a="outer"
>>> def test():
...  print a
...  a="inner"
...  print a
...  return
... 
>>> test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in test
UnboundLocalError: local variable 'a' referenced before assignment
ähnlich wie in JS ... hmpf ...
BlackJack

@LanX: Ich sehe da die Vorteile: Es kann nicht passieren dass sich ein und der selbe Name zum Beispiel in einer Schleife in verschiedenen Durchläufen auf verschiedene Sichtbarkeitsbereiche bezieht. Und da der Compiler schon feststellt welche Namen lokal sind, wird schnellerer Code generiert. Lokale Variablen werden nämlich nicht in einem Dictionary gespeichert, sondern in einem Array und im Bytecode werden die lokalen Namen über einen festen Index referenziert.
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

BlackJack hat geschrieben:Ich sehe ``nonlocal`` nicht als essentiell wichtig an. Python hat Klassen, man bekommt da also nichts, was man vorher nicht auch relativ einfach ausdrücken konnte. Klassen sind ein wichtiger Bestandteil von Python und nichts exotisches. Wenn man sie braucht, sollte man sie auch verwenden.
Naja du argumentierst Python habe "richtige" Closures und dann sagste man solle OOP dafür nutzen...

Es gibt halt ein riesiges funktionales Erbe aus der LISPischen ecke, wenn ich jedes Pattern erst halb auf Pythons OOP umschreiben muss, ist das nicht dasselbe wie wenn ich es direkt umsetzen kann. (wie z.B. in "Higher Order Perl" für Perl beschrieben.)

Das mag für dich nicht essentiell sein, mich schränkt es ein.

Und um den Kreis zu schließen JS bietet es vollständig an¹.

Mithilfe von Closures kannste dort die vermissten OOP Features mehr als kompensieren.

Dazu muss man sich auch in Closures wohlfühlen und denken können. Das meinte ich damit, dass ein reiner Python POV dann viele Möglichkeiten in JS übersieht.

1) zugegeben, das Fehlen von echten Blockscopes durch Curlies zwingt einen manchmal diesen Workaround mit anonymen Funktionen zu nutzen, die sofort in-place ausgeführt werden... auch etwas nervig.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

LanX hat geschrieben:
Darii hat geschrieben: Das seltsame this, auf das man sich nicht verlassen kann (var self = this *hust*).
ich kann dir nicht folgen... Beispiel?
Wenn man eine Methode (Funktion) eines Objektes beispielsweise an einen Event-Handler bindet verweist this nicht mehr auf das aktuelle Objekt aus dem diese Methode stammt sondern auf den Kontext des Event-Handlers. http://www.digital-web.com/articles/sco ... avascript/ Deswegen muss man dann das magische this vorher an eine lokale variable binden, um später noch auf das eigene Objekt zugreifen zu können. In Python wird das verhindert weil man auf normalem Wege nur an die „bound method“s rankommt. In anderen Sprachen (Java, C++) ergibt sich die Problematik auch nicht weil man sowieso nicht an den Funktionszeiger einer Methode rankommt ohne sich auf den Kopf zu stellen.
hä??? ... gibts außer Python eine andere (nichtakademische) Sprache die per default localisiert und wo man explizit "nonlocal"-isiseren muss (wenn man denn kann)?
Ja. Java, C ... such dir was aus.
"var" ist nervig weil es für den ganzen Scope - also auch vorhergehenden Code - gilt.¹
Deswegen bemängelt Crockfords JS-Lint es auch wenn du die var-Deklarationen nicht am Funktionsanfang machst.
Wie sollte es denn sonst funktionieren? Erst ein bisschen mit der Globalen Variable a rumspielen, dann lokal machen und irgendwann später wieder zu einer globalen Variable machen. Wenn das nicht unübersichtlich wäre…

Das ist IMHO ein fettes Plus! Ich bevorzuge - schon aus Designgründen - Mixins. Die Nützlichkeit der Mehrfachvererbung ist m.E. ein Mythos.
Sprich, da es dafür in Javascript keine Sprachmittel gibt, denkt sich jeder ein eigenes System aus, um gemeinsames Verhalten in die Prototypen zu kopieren.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Darii hat geschrieben:[Wie sollte es denn sonst funktionieren? Erst ein bisschen mit der Globalen Variable a rumspielen, dann lokal machen und irgendwann später wieder zu einer globalen Variable machen. Wenn das nicht unübersichtlich wäre…
Das ist tatsächlich, wie es bei (korrekter) lexikografischer Bindung funktionieren sollte.

Code: Alles auswählen

a = 1
def f():
  print(a) # dies müsste eigentlich 1 sein, ist in Python aber ein Fehler
  a = 2 # jetzt habe ich eine lokale Variable, die die globale überschattet
  print(a) # dies müsste 2 sein
print(a) # dies ist 1
f() # müsste 1 und 2 ausgeben, bricht aber ab
print(a) # dies ist wieder 1
Vergleiche dazu in Scheme

Code: Alles auswählen

(define a 1)
(define f (lambda ()
  (print a) ; dies ist 1
  (let ((a 2)) 
    (print a)))) ; dies ist 2 (die Klammern machen die Bindung deutlicher)
(print a) ; gibt 1 aus
(f) ; gibt 1 und 2 aus
(print a) ; gibt 1 aus
In Python hat man sich allerdings dafür entschieden, dass eine Zuweisung innerhalb einer Funktion die Variable als lokal in der gesamten Funktion erklärt und komplett eine gleichnamige globale Variable überschattet. Die einzige Möglichkeit, eine lokale Variable zu deklarieren ist ja implizit durch das Zuweisen eines Wertes. In Scheme geschieht es explizit mittels "let" welches auch gleich noch den Gültigskeitsbereich der Variable klar macht. In JavaScript funktioniert es mit "var" ähnlich wie bei Python, mit der Ausnahme, dass der folgende Fall leider nicht klar definiert ist und sich verschiedene JavaScript-Interpreter unterschiedlich verhalten:

Code: Alles auswählen

if (true) {
  function f() { return 1; }
} else {
  function f() { return 2; }
}
f();
Einige sagen hier 1, andere 2. Würde man var f = function(){...} schreiben - was eigentlich gleichbedeutend sein sollte - funktioniert es AFAIK wie erwartet. In der nächsten EcmaScript-Version soll es daher statt (bzw. zusätzlich zu) "var" noch "let" geben (die Monkey-Implementationen haben das schon), welches sich korrekt lexikografisch wie in Scheme verhält.

Stefan
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Darii hat geschrieben:
hä??? ... gibts außer Python eine andere (nichtakademische) Sprache die per default localisiert und wo man explizit "nonlocal"-isiseren muss (wenn man denn kann)?
Ja. Java, C ... such dir was aus.
Das ist für Java falsch. Die Sprache verhält sich im Gegensatz zu Python so, wie bereits in meinem Scheme-Beispiel gezeigt und wie man's eigentlich erwarten würde. Für C kann ich's nicht sagen und habe keine Lust, das auszuprobieren. Ruby hingegen macht es wie Python und würde in dem folgenden Programm einen NameError liefern:

Code: Alles auswählen

a = 1
def f()
  puts a
  a = 2
  puts a
end
f()
Und das nonlocal ist glaube ich einzigartig. Schachtelt man in Ruby Closures (mit Methoden geht das gar nicht), kann man standardmäßig die freien Variablen auch ändern. Da Java gar keine Closures kennt und auch Methoden nicht schachteln kann, kommt das Problem eigentlich nicht vor. Nimmt man anonyme innere Klassen mit Methoden als Closures für Arme an, zwingt Java einen hier, die freien Variablen extra als unveränderlich zu deklarieren, damit man sie benutzen darf.

In einer früheren Lua-Version gab es IMHO mal die Notwendigkeit, etwas ähnliches wie "nonlocal" zu deklarieren (irgendwas mit upvals oder so), doch das man man schon vor Jahren zugunsten der gewohnten lexikografischen Bindung aufgegeben.

Stefan
Antworten