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.
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
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

sma hat geschrieben:
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.
Ich bezog mich auch nicht auf das nonlocal/whatever sondern auf das Verhalten, dass Variablen immer global sind. In Javascript muss/kann man ja wie in Python Variablen nicht explizit deklarieren (bis global, nonlokal, var). Die Deklaration erfolgt implizit durch Zuweisung. Wenn ich in Javascript eine Variable benutze ist sie automatisch global. Wenn ich in Java eine Variable deklariere ist sie lokal.

Code: Alles auswählen

function x() { foo = 23 }
x();
foo; // -> 23
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Darii hat geschrieben: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.
Die wichtige Erkenntnis aus dem Self-Projekt (vor 20 Jahren) war, dass protoypische Vererbung mittels Delegation ein so mächtiges Sprachkonzept ist, dass man damit alle andere Systeme simulieren kann. Das man sich damit also verschiedene klassenbasierten Vererbungskonzepte selbst bauen kann, spricht IMHO für und nicht gegen die Sprache und die Wahl von Selfs System für JavaScript.

Warum wurde Vererbung überhaupt erfunden? Um Code zu sparen. Es war (und ist) ein reines Implementationsmittel und man sollte (was leider nur wenige Programmiersprachen machen) eine Subtyp-Beziehung strickt von der Vererbung trennen. Einfache Vererbung ist nicht mächtig genug. Mehrfache Vererbung hat aber Probleme, wenn man statische Klassendefinitionen mit statischen Feldern hat, weil nicht klar ist, ob es diese beim "Diamand-Problem" nun mehrfach gibt oder nicht. Außerdem ist die Serialisierung gleichnamiger Methoden nicht trivial. Das simple Verfahren von Python1.x hat sich nicht bewehrt und der von Dylan stammende Algorithmus (AFAIK der einzige der bislang gefunden wurde, der sich in der Praxis bewährt) wurde erst relativ spät entdeckt und ist auch nicht gerade einfach zu verstehen. Zudem hätte es nicht "super" wie bei Smalltalk heißen dürfen, sondern besser etwas wie "next" oder "call-next-method" wie bei CommonLisp und Dylan, was klar macht, dass hier die nächste weniger spezielle Methode aufgerufen werden soll, die nicht notwendigerweise aus einer Oberklase stammt. Schon viel früher hat man entdeckt, das Mixins (ich meine, die stammen aus Flavors, einem sehr frühen objektorientierten Lisp) alle guten Eigenschaften der Mehrfachvererbung haben ohne die Probleme. Formalisiert man Mixins und fügt ihnen abstrakte Methoden hinzu, hat man traits, ich kenne diesen Begriff wieder von Self. Inzwischen greifen immer mehr Sprachen (z.B. Scala und Fortress) dazu. Self hat zudem auch einen supersimplen Ansatz, der Serialisierungsproblem von Methoden zu lösen: Bei Mehrdeutigkeit gibt es Laufzeitfehler. Das missfällt aber Sprachtheoretikern, weil man so keine Vorhersagen über das Programm machen kann, ohne es auszuführen. Ach, es gibt auch jemanden, der hat Traits für JavaScript implementiert. Rubys Module sind konzeptionell übrigens auch Mixins bzw. Traits. In Python kann man die Mehrfachvererbung ebenfalls für Mixins nutzen, wenn man will. Komischerweise macht das kaum einer und irgendwie gibt es eine Art ungeschriebenes Gesetz, doch immer noch von einer Klasse zu erben. Ich glaube ja, das liegt daran, weil sich die Leute nicht davon trennen können, Vererbung gleichzeitig als Subtyp-Hierarchie anzusehen. Hatte ich schon mal Cecil erwähnt - das ist ein Zwitter aus Self und CommonLisp mit einem optionalen statischen Typsystem, welches Vererbung und Typen korrekt trennt. War eigentlich eine recht elegante Sprache, IMHO.

Stefan
BlackJack

@LanX: Wenn Du LISP programmieren willst, dann programmiere doch einfach in LISP. Wenn Du Dich gedanklich nicht auf eine andere Sprache einlassen willst, sondern in ihr genau so weiterprogrammieren willst, wie in einer Sprache die Du schon kennst, warum willst Du dann überhaupt eine andere Sprache verwenden. Mit dieser Argumentation kommt die Freiheit, dass jeder in seinen eigenen Mustern schreibt, und es für andere schwierig wird den Quelltext zu verstehen, warten, und zu erweitern. Eines *der* Probleme die ich mit LISP und Scheme habe, wenn sich jeder seine eigene DSL daraus zimmert.

Umgekehrt erwarte ich auch nicht, dass andere Sprachen wie Python funktionieren, zum Beispiel das es dort eine Python-artige Vererbung gibt. Im Grunde wirfst Du hier immer unterschwellig vor, die Leute wären zu unflexibel sich auf JavaScript einzulassen und hängen an den Spracheigenschaften von Java oder Python, und im Gegenzug jammerst Du rum, dass Du Muster von LISP nicht 1:1 auf Python übertragen kannst, und Dich die Sprache tatsächlich nötigt, sich mit ihrem OOP-Modell auseinanderzusetzen.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

sma hat geschrieben:
Darii hat geschrieben: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.
Die wichtige Erkenntnis aus dem Self-Projekt (vor 20 Jahren) war, dass protoypische Vererbung mittels Delegation ein so mächtiges Sprachkonzept ist, dass man damit alle andere Systeme simulieren kann. Das man sich damit also verschiedene klassenbasierten Vererbungskonzepte selbst bauen kann, spricht IMHO für und nicht gegen die Sprache und die Wahl von Selfs System für JavaScript.
Aber im Gegensatz zu Self gibt es bei Javascript nur einen Prototypen. Bei Self kann man ja beliebig viele parent-Slots haben. JavaScript ist an der Stelle nicht flexibel genug um das mit Sprachmitteln zu auszugleichen. Ich hab nichts grundsätzliches gegen das Objektmodell von Javascript. Die Sprache selbst finde ich einfach nicht so toll (um nicht zu sagen grausam). Javascript ist einfach als reine Scriptsprache konzipiert und dementsprechend wurde sie auch entworfen. Siehe die ganzen grandiosem impliziten Typumwandlungen. Sowas ist bei dynamisch typisierten Sprachen tödlich. Dann knallt es nämlich nichtmal zur Laufzeit, sondern das Programm funktioniert einfach nicht wie gedacht.
sma hat geschrieben:In Python kann man die Mehrfachvererbung ebenfalls für Mixins nutzen, wenn man will. Komischerweise macht das kaum einer und irgendwie gibt es eine Art ungeschriebenes Gesetz, doch immer noch von einer Klasse zu erben.
Man könnte auch einfach import nutzen, leider ist aus irgendeinem mir unverständlichen Grund der sternchen-Import innerhalb von Klassen „deprecated“.
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

BlackJack hat geschrieben:@LanX: Wenn Du LISP programmieren willst, dann programmiere doch einfach in LISP.
Na, hört sich an wie geh doch rüber, wenn's dir nicht passt.

Zurück zum Start, es ging darum dass nicht nur Javascript Defizite hat und ich z.B. bei Python "richtige Closures" und komplexe Lambdas vermisse.

Ich könnte auch ne lange Liste dessen abgeben, was ich in Perl vermisse. (Docstrings, Instanzvariablensigils wie in Ruby, Macros,...etc. pp.)

Das ist ein Diskussionsforum...wenn ich meine Kritik nicht äußere, kann ich nicht aus der Widerlegung lernen. :-)
BlackJack

@Darii: Der ist nicht "deprecated". Schon in der ``import``-Doku von Python 1.4 steht der Satz `"The from form with * may only occur in a module scope."` Code der solche Importe nutzt(e) war also schon immer ausserhalb der Spezifikation, auch wenn der Compiler das früher mal durchgehen liess.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

BlackJack hat geschrieben:@Darii: Der ist nicht "deprecated". Schon in der ``import``-Doku von Python 1.4 steht der Satz `"The from form with * may only occur in a module scope."` Code der solche Importe nutzt(e) war also schon immer ausserhalb der Spezifikation, auch wenn der Compiler das früher mal durchgehen liess.
Deswegen die Anführungsstriche. Aber was heißt früher? In 2.6 gehts noch.
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

Darii hat geschrieben: In Javascript muss/kann man ja wie in Python Variablen nicht explizit deklarieren (bis global, nonlokal, var). Die Deklaration erfolgt implizit durch Zuweisung. Wenn ich in Javascript eine Variable benutze ist sie automatisch global. Wenn ich in Java eine Variable deklariere ist sie lokal.

Code: Alles auswählen

function x() { foo = 23 }
x();
foo; // -> 23
"var" ist die Deklaration, und vergleichbar zu "int" usw in C und Java.

Die "undeklarierten" Variablen sind in JS auch nicht wirklich "global", sondern sind Attribute des umgebenden Objektes, sprich im Browser window.

Code: Alles auswählen

javascript: a="winki winki";alert(window.a)
wo JS nach nicht-lokalen Variablen sucht kannst du (halbwegs) mit with() steuern:

Code: Alles auswählen

O={a:"hier"};
with (O) {alert(a)};
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

LanX hat geschrieben:"var" ist die Deklaration, und vergleichbar zu "int" usw in C und Java.
Habe ich doch geschrieben.
Die "undeklarierten" Variablen sind in JS auch nicht wirklich "global", sondern sind Attribute des umgebenden Objektes, sprich im Browser window.
Halt genauso global wie Python-global.
wo JS nach nicht-lokalen Variablen sucht kannst du (halbwegs) mit with() steuern:
Aber auch nur die Suche

Code: Alles auswählen

obj = {}
with(obj) { a = 23 }
obj.a // undefined
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

Darii hat geschrieben:
LanX hat geschrieben:"var" ist die Deklaration, und vergleichbar zu "int" usw in C und Java.
Habe ich doch geschrieben.
Ja, aber in diesen, und den meisten anderen Sprachen brauchst du einen Deklarationsbefehl damit es lokal ist.

Bei Python (und wie wir jetzt wissen Ruby) ist es umgekehrt. Da brauchst/bräuchtest du ein nonlocal.¹

Dieser eine Punkt der dich an JS also nervt, begegnet dir fast überall wieder.

¿oder was hattest du gemeint mit:
Darii hat geschrieben: Und die umständliche Scoping-Regel, der man zu verdanken hat, dass man vor praktisch jede Variable var schreiben muss.
?

1) wobei ich jetzt nicht glaube das "nonlocal" in Py selbst eine Deklaration ist, die Variable muss bereits in einem äußeren Scope deklariert worden sein, oder wird damit implizit eine globale Variable deklariert???
BlackJack

@LanX: Der Punkt beim ``var`` begegnet einem nicht überall. Bei welchen Sprachen kann man denn so einfach aus versehen den globalen Namensraum vollmüllen? In C, Java, C#, usw. jedenfalls nicht -- da muss man die Variable auch irgendwo da draussen noch einmal explizit deklarieren, sonst kompiliert es gar nicht erst. Man muss bei JavaScript also immer an das ``var`` denken, denn das ist ja das was man in 99% der Fälle haben will, aber es ist nicht so offensichtlich wenn man es mal vergisst. Weil das trotzdem noch "funktioniert".
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

BlackJack hat geschrieben: In C, Java, C#, usw. jedenfalls nicht --
Nun das sind alles statisch typisierende Sprachen, wo es natürlich keine "Defaultdeklaration" ohne Keyword geben kann!

Was ich meinte ist dass "var" den gleichen Scope erzwingt wie "int".

Ich kenne es schon traditionell von BASIC, das es einen "local"-Befehl gibt, das spiegelt sich auch in den meisten mir bekannten Scriptsprachen wieder. (in Perl steht "my" analog zu "var"¹ für lexikalische Variablen)

Bereits LISP muss man explizit mit "let" lokalisieren, während "set" global ist.

Ergo ist das Verhalten von Python und Ruby² IMHO nicht die Regel.

Dafür das man nicht versehentlich einen globale Variable deklariert kann man üblicherweise eine explizite Deklaration erzwingen (in Perl mit "use strict;")³

Ich denke jslint kann für solche "strictness" in JS benutzt werden.

Darüber welches Verhalten (local vs nonlocal) nun mehr Vorteile hat, will ich mir jetzt kein Urteil anmaßen...

Worauf ich hinaus wollte, dass JS sich so verhält wie die meisten anderen Scriptsprachen, kann man wohl kaum als spezifische Kritik an JS anführen...


1) allerdings global ist bei mir var nicht lexikalisch!

Code: Alles auswählen

javascript: var a=10; alert(window.a)
grummel...

NACHTRAG:
2) in Ruby ist es tatsächlich nochmal etwas anders, dort gibts einen expliziten Sigil für global vars
http://www.rubyist.net/~slagell/ruby/globalvars.html

3) interessant, ECMA-Script 5 führt auch "use strict" ein...
Zuletzt geändert von LanX am Sonntag 25. Juli 2010, 18:30, insgesamt 2-mal geändert.
BlackJack

@LanX: Wieso kann man das nicht als Kritik an JavaScript anführen? Nur weil Perl genau so dämlich an der Stelle ist, wird's bei JavaScript ja nicht besser. Im Gegenteil -- JavaScript ist wesentlich jünger, da hätte man ja aus den Fehlern lernen können.

BASIC anzuführen ist an der Stelle ein wenig problematisch, weil es das so nicht gibt. Das original BASIC hatte keine Funktionen/Sichtbarkeitsbereiche und in Dialekten wird es wahrscheinlich alle möglichen Semantiken geben.
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

@BlackJack:
ich sagte "spezifische" Kritik an JS!¹


Du kannst natürlich von deinem Py-POV generell alle anderen Sprachen dafür kritisieren, das sie nicht per default lokalisieren (Aber auch diesbzgl war ich deutlich)

NACHTRAG:
1)vielleicht wäre die Wortwahl "JS-spezifische Kritik" deutlicher gewesen.
BlackJack

@LanX: Ich kritisiere das nicht aus meinem "Py-POV".
Antworten