Kann man sich eigene Statement´s programmieren?

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.
Andyh
User
Beiträge: 319
Registriert: Dienstag 8. Januar 2008, 19:52
Kontaktdaten:

Hallo

Mal so ne Frage (google und die Board Suche haben nichts gebracht) ist es möglich Statements zu Programmieren?

Mal schnell was ich meine:

bis her:

Code: Alles auswählen

import hallo

hallo("Dies ist die Nachricht") #Es geht ein fenster auf und ginb den String aus
neu

Code: Alles auswählen

import hallo
hallo "Dies ist die Nachricht" #Es geht ein fenster auf und ginb den String aus
Gruß
Andyh[/code]
Meinen Dickschädel schon bemerkt?
Ich bin jetzt FACHARBEITER (Zerspanungsmechaniker)!!!
[code]import sys

if sys.platform == "win32":
print "this program only runs on operating systems!!!"
sys.TotalError()[/code]
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

Meines wissens geht das nicht.
Die Frage wäre auch, wozu man das möchte, solange du "statements" möchtest, so dass du einen Namen und Argumente angibst, und damit eine Aktion auslösen möchtest, ist der Hauptunterschied unterschied zu einer Funktion (oder einem beliebigen Callable, btw), dass du runde Klammern brauchst.

Was spricht gegen eine Funktion? Versuchst du, ruby-eske konfigurationsdateien zu basteln, und dir ist die Optik wichtg?
Zuletzt geändert von keppla am Sonntag 9. November 2008, 11:28, insgesamt 1-mal geändert.
Andyh
User
Beiträge: 319
Registriert: Dienstag 8. Januar 2008, 19:52
Kontaktdaten:

Hallo

Wie so oft bei mir hat das keinen keinen sinn ich möchte nur wissen ob man sowas machen kann.

Scheint ja nicht so.

Gruß
Andyh
Meinen Dickschädel schon bemerkt?
Ich bin jetzt FACHARBEITER (Zerspanungsmechaniker)!!!
[code]import sys

if sys.platform == "win32":
print "this program only runs on operating systems!!!"
sys.TotalError()[/code]
BlackJack

@Andih: In reinem Python geht das nicht. Wird von den Python-Entwicklern als Stärke angesehen und nicht als Schwäche.

Ein Grund warum das keine so gute Idee in Python ist: Schlüsseworte dürfen nicht als Bezeichner verwendet werden. In Deinem Beispiel würde `hallo` dann nicht mehr als Name verwendbar sein. Auch nicht als Modulname, das ``import`` ginge dann zum Beispiel nicht mehr.

Schau Dir vielleicht mal EasyExtend an wenn Du trotzdem mit Syntaxänderungen spielen möchtest.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Andyh hat geschrieben:Wie so oft bei mir hat das keinen keinen sinn ich möchte nur wissen ob man sowas machen kann.
Nein. In Lisp ist sowas jedoch weit verbreitet, das Stichwort dort ist "Makro".
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Andyh
User
Beiträge: 319
Registriert: Dienstag 8. Januar 2008, 19:52
Kontaktdaten:

Hallo

Gut verstanden, geht nix

Gruß
Andyh
Meinen Dickschädel schon bemerkt?
Ich bin jetzt FACHARBEITER (Zerspanungsmechaniker)!!!
[code]import sys

if sys.platform == "win32":
print "this program only runs on operating systems!!!"
sys.TotalError()[/code]
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Ist vermutlich auch gut so. Sonst würde der Progger irgendwann nicht mehr genau wissen, was er jetzt als Statement und was als Methode definiert hat. Okay, ein guter Programmierer kennt seinen Code, aber es stiftet auf jeden Fall Verwirrung... :)
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Wer Guy Steeles (legendären) OOPSLA-Vortrag Growing a Language kennt, weiß, dass er die Erweiterbarkeit einer Sprache für eine wichtige Eigenschaft hält (Somit ist dann auch seine neue Sprache Fortress extrem erweiterbar). Dies ist eine Schwäche vieler existierender Sprachen wie Java, C, C,# aber auch Python. In C# wird es dadurch ausgeglichen, dass Microsoft fast jedes Jahr eine neue Version mit erweiterter Syntax raushaut :) Andere Sprachen - prominentestes Beispiel ist sicherlich Lisp, aber auch Forth oder Smalltalk sind hier stark - kann man als Entwickler derart erweitern, dass irgendwelche Kontrollstrukturen oder sonstige Syntax nichts besonderes sind. Das erlaubt es, mit Hilfe von DSLs die Programmiersprache optimal an das jeweilige Problem anzupassen. Ruby schafft es, obwohl man die grundlegende Syntax nicht anpassen kann, dennoch so auszusehen - weil man anscheinend neue Anweisungen bauen kann, indem man bei Funktionsaufrufen die Klammern weglassen darf. Nachteil von DSLs ist, dass es kein festes Set an Syntax gibt, an dem sich der Anfänger orientieren kann.

Stefan
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Ein Statement ist nicht umsonst eins, sondern ist klar trennbar von einer Funktion. Eine Funktion hat immer eine Aufgabe, die direkt mit Daten zu tun hat. Ein Statement dagegen wird bei Dingen verwendet, für die man auch Funktionen verwenden müsste, die aber nichts mit Daten direkt zu tun haben. Beispiel Kontrollstrukturen. Braucht man immer, haben aber nichts mit Daten (also Eingabe -> Ausgabe) zu tun, sondern nur mit der Sprache selbst. Deswegen finde ich die Art und Weise, wie Python das löst, sehr gelungen. Einzig das print Statement fällt da aus der Reihe, bis py3k.
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

sma hat geschrieben:weil man anscheinend neue Anweisungen bauen kann, indem man bei Funktionsaufrufen die Klammern weglassen darf.
ich würde sagen, die schaffen das eher durch anonyme Funktionen/Codeblöcke und dadurch, dass alle Klassen erweiterbar sind.
Dass man nach (anfangs) etwas merwürdig anmutenden regeln sowohl runde als auch geschweifte Klammern weglassen kann/muss soll wohl eher der Lesbarkeit dienen, würde die entstehenden DSLs aber nicht verhindern, sondern nur noch mehr nach Smileygemetzel aussehen lassen.
BlackJack

@str1442: Ich weiss nicht ob ich Deine Aussage richtig verstehe. Kommt es nicht auch sehr stark darauf an, was man als "Daten" ansieht? Wenn man Code auch als Daten ansieht, ist Deine Unterscheidung hinfällig. Und da in Python auch Module, Funktionen und Klassen Objekte sind, ist die Unterscheidung zwischen Daten und Code auch schon recht aufgeweicht. Natürlich nicht so stark wie zum Beispiel bei Lisp, Scheme, oder Io.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

str1442 hat geschrieben:Ein Statement ist nicht umsonst eins, sondern ist klar trennbar von einer Funktion.
Das ist eine Design-Entscheidung, die nicht jede Programmiersprache so trifft. In Lisp gibt es keine Anweisungen (statements) sondern nur Ausdrücke (expressions). Bei Smalltalk ist es genau und Forth kennt nur Wörter, die den Stack manipulieren.

Ich halte die Entscheidung für eine Einschränkung der Flexibilität, weil man a) die Statements explizit definieren muss und b) es zu Redundanzen kommt, etwa wenn man nicht nur bedingte Anweisungen sondern auch bedingte Ausdrücke (in Python das `consequence if condition else alternative` und in {}-Sprachen das `cond ? cons : alt`) haben möchte.
str1442 hat geschrieben:Beispiel Kontrollstrukturen. Braucht man immer, haben aber nichts mit Daten (also Eingabe -> Ausgabe) zu tun, sondern nur mit der Sprache selbst.
Bedingte Ausdrücke erwähnte ich ja schon. Der Kontrollfluss ist außerdem untrennbar mit der Datenverarbeitung verbunden und nicht davon getrennt.

In Lisp ist das `if` (oder das allgemeinere `cond`) traditionell eine "Special Form" und damit eigentlich eine primitive Anweisung, doch das Lamda-Kalkül erklärt, wie man bedingte Anweisungen zu bedingten Ausdrücken mit Hilfe von lambda und Funktionen höherer Ordnung machen kann. Statt Funktionen kann man auch Objekte benutzen, so wie es Smalltalk macht.

Dort gibt es Block-Objekte, die Programmfragmente repräsentieren und denen man die Nachricht "value" schicken kann (also die Methode "value" aufrufen kann, doch man nennt es eben Nachrichten schicken). Es gibt zwei Klassen True und False für die beiden einzigen Exemplare true und false und diese Klassen implementieren Methoden wie z.B. ifTrue:ifFalse:, die zwei Blöcke übergeben bekommen und danach dann einen auswählen. In Python-Syntax sähe das so aus:

Code: Alles auswählen

class True:
  def ifTrue_ifFalse_(self, trueBlock, falseBlock):
    return trueBlock.value()

class False:
  def ifTrue_ifFalse_(self, trueBlock, falseBlock):
    return falseBlock.value()
und wie man sieht, ist das alles, was notwendig ist, um eine bedingte "Anweisung" in der Sprache mit primitiveren (aber mächtigeren) Mitteln zu realisieren. Keine Notwendigkeit, dies als Teil der Syntax zu sehen.

Gleichzeitig kann ich mir beliebige weitere Kontrollstrukturen bauen wie ein "while" oder ein "switch-case".
str1442 hat geschrieben:Einzig das print Statement fällt da aus der Reihe, bis py3k.
Nein, auch andere: Z.B. `import`. Vergleiche dies mit der Funktion `__import__`. Über `break` und `continue` könnte man streiten. Diese könnte man auch mit `raise` und speziellen Exceptions realisieren. Und `raise` müsste auch keine Anweisung sein. Objektorientiert würde ich erwarten, dass ich einem Exception-Objekt eine entsprechende Nachricht schicken könnte.

Die Menge der Anweisungen ist einfach eine Design-Entscheidung, die IMHO hauptsächlich vom Geschmack des Sprachdesigners beeinflusst ist.

Stefan
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

@str1442: Ich weiss nicht ob ich Deine Aussage richtig verstehe. Kommt es nicht auch sehr stark darauf an, was man als "Daten" ansieht? Wenn man Code auch als Daten ansieht, ist Deine Unterscheidung hinfällig. Und da in Python auch Module, Funktionen und Klassen Objekte sind, ist die Unterscheidung zwischen Daten und Code auch schon recht aufgeweicht. Natürlich nicht so stark wie zum Beispiel bei Lisp, Scheme, oder Io.
Naja, was wohl etwas schlecht ausgedrückt.
Eine Klasse bildet ja den Typ eines Objektes ab.
Eine Methode eine Aktion seitens eines Objektes.
Eine Funktion bildet eine Tätigkeit ab, die meist sehr generell gehalten ist.
Ein Statement dagegen hat ja nichts direkt mit einer Tätigkeit zutun. Außer aus der Sicht einer Sprache, intern ist es dort natürlich eine Tätigkeit. Aber für ein Programm in dieser Sprache ist "if" oder "return" keine Tätigkeit. Deswegen macht es auch keinen Sinn, zig Statements zu definieren oder gar neue, ziemlich schnell ist jede dieser "nicht-Tätigkeiten" in Bezug auf das Programm definiert.

Im Grunde meine ich, das Statements etwas aus der Reihe fallen, auch wenn sie direkt mit den Daten verbunden sind.

Hm, immernoch wirr :?

@sma

Mir ist schon klar, das andere Sprachen (und insbesondere Funktionale) diese Dinge anders umsetzen, aber viele Sprachen nutzen Statements (oder ähnliche Dinge) eben nicht wie Funktionen. Ein Statement ist eben eine Anweisung an die Sprache (bzw deren Interpreter / Compiler), aber nichts, was unmittelbar mit den zu verarbeitenden Daten / Objekten zu tun hat. Statements fallen aus der Reihe, das wollte ich damit ausdrücken. Sieht man auch in C ganz gut: If, for usw sind dort ja Funktionen und haben entsprechende Funktionsköpfe, legen dann aber noch einen Funktionsbody an, der ja nicht direkt mit dem Aufruf zu tun hat. Sowas macht man eigentlich nur bei der Definition einer Funktion, nicht aber beim direkten Anwenden. Wenn man also Statements generell als Syntax Element einführt, muss man später nicht auf derartige Ausnahmen zurück greifen (es sei denn, man macht es sowieso komplett anders).
Ich halte die Entscheidung für eine Einschränkung der Flexibilität, weil man a) die Statements explizit definieren muss.
Das wollte ich ja darstellen, das man nicht sonstwieviele Statements definieren kann. Ansonsten gibts ja keinen Unterschied zu Funktionen mehr.
b) es zu Redundanzen kommt, etwa wenn man nicht nur bedingte Anweisungen sondern auch bedingte Ausdrücke (in Python das `consequence if condition else alternative` und in {}-Sprachen das `cond ? cons : alt`) haben möchte.
Inwiefern sollte es da zu Überflüssigem kommen? Ich würde sowas übringens rein logisch nicht als Ausdruck ansehen, sondern als eine Vereinfachung der Variablenzuweisung. Die Bedeutung eines Statements (wie ich es hier auffasse) bleibt auch hier erhalten.

Danke für den kleinen Exkurs :D

@Import: Gut, stimmt, im Grunde ist import einer Tätigkeit ähnlicher als etwas anderem.

@raise: Das meine ich zum Beispiel mit "Nicht-Tätigkeit". Es tut nichts, was man nicht auch Objekt Orientiert machen könnte. Aber es ist in einem Programm auch irgendwo fehlplatziert, mit einem Objekt zu arbeiten, das im Grunde nur die Sprache als Solches etwas angeht (Welche Methoden sollte ein Exception Objekt denn noch haben, mit denen man arbeiten könnte? Irgendwo musses ja aufhören, man kann also auch nicht konsequent bleiben). Da ist es mir lieber, ein neues Exception Objekt zu erstellen, aber den Rest Python machen zu lassen (durch raise zb), anstatt nun mit irgendwelche Objekt Methoden zu arbeiten, die etwas tiefer ins Sprachdesign greifen.

Hoffentlich ist es jetzt klarer geworden, wie ich das meine.
BlackJack

@str1442: Also ich finde es wird immer unklarer und widersprüchlicher.

`return` ist durchaus eine Tätigkeit und eine Auswahl eines auszuwertenden Codes mit `if` zu treffen, kann man ebenfalls als Tätigkeit ansehen. Beides hat auch unmittelbar mit den Daten des Programms zu tun. `return` sogar ziemlich direkt mit den Daten.

`if` und `for` sind in C *Funktionen*!? Wäre mir neu.

Wenn Du keine Ausnahmen haben willst, dann musst Du Statements gerade *weglassen*. Siehe zum Beispiel Lisp und Scheme oder bei einer nichtfunktionalen, OOP Sprache Io. Da sind die typischen "Statements" syntaktisch nicht von Funktionen zu unterscheiden und man kann selber Funktionen/Methoden implementieren, die "Statements" entsprechen. Da gibt's dann natürlich keinen Unterschied mehr zwischen "Statements", also in diesem Fall in der Standardbibliothek implementierte Varianten von `if`, `for`, usw., und eigenen Funktionen/Methoden. Aber warum muss es den geben?

Es kommt zu "überflüssigem" wie dem ``a if c else b`` weil das in anderen Sprachen schon vom "normalen" `if` abgedeckt wird. Ausdrücke sind Konstrukte, die zu einem Ergebnis ausgewertet werden. Damit ist das Konstrukt per Definition ein Ausdruck. Es ist ja überhaupt nicht an Zuweisungen gebunden -- man kann es überall verwenden, wo ein Wert bzw. eben ein Ausdruck erwartet wird.

`raise` ist genau wie `return` eine Tätigkeit. Wieso sollte es keine Objekte geben, die "Interna" der Sprache repräsentieren? Und wieso muss man irgendwo aufhören? Schau Dir mal Io an. Mit der Argumentation dürfte es zum Beispiel kein `gc`- oder `compiler`-Modul in Python geben. Oder bei PyPy die Metaebene, über die man an die Objekte des Interpreters kommunizieren kann.

Was ist der Vorteil eines ``raise``-Statements gegenüber einer Methode auf Ausnahmen? Ein Ausnahme-Objekt könnte noch eine `catch()`-Methode haben, eine Methode die den Stacktrace liefert, und eine `pass()`-Methode, die die Methode erneut "raise"t. Siehe Io.

Und in Python gibt's doch auch eine Menge (magische) Methoden, die in die Bedeutung von Statements eingreifen. Was ``for`` genau macht, hängt massgeblich davon ab, was der Programmierer als `__iter__()` auf Objekten implementiert. Das ``with``-Statement wird duch `__enter__()` und `__exit__()` implementiert, in den Import-Mechanismus kann man sich einklinken, usw. Man kann da in Python sehr viel machen, indem man der vorhandenen Syntax ziemlich weitgehend eigene Bedeutung unterschieben kann, man kann nur keine neue Syntax einführen.
Qubit
User
Beiträge: 128
Registriert: Dienstag 7. Oktober 2008, 09:07

Andyh hat geschrieben:Hallo

Mal so ne Frage (google und die Board Suche haben nichts gebracht) ist es möglich Statements zu Programmieren?

Mal schnell was ich meine:

bis her:

Code: Alles auswählen

import hallo

hallo("Dies ist die Nachricht") #Es geht ein fenster auf und ginb den String aus
neu

Code: Alles auswählen

import hallo
hallo "Dies ist die Nachricht" #Es geht ein fenster auf und ginb den String aus
[/code]
Ohne in die "Hartverdrahtung" einzugreiffen...

Code: Alles auswählen

import code
class CustomCmd(code.InteractiveConsole):
     def raw_input(self, prompt=None):
         while 1:
             text = raw_input(prompt)
             if text.startswith("hallo"):
                 print "Fenster mit ",' '.join(text.split(' ')[1:])
             else:
                 return text

cmd = CustomCmd()
cmd.interact()


Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(CustomCmd)
>>> hallo "Dies ist die Nachricht" 
Fenster mit  "Dies ist die Nachricht" 
>>> 
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

str1442 hat geschrieben:Mir ist schon klar, das andere Sprachen (und insbesondere Funktionale) diese Dinge anders umsetzen, aber viele Sprachen nutzen Statements (oder ähnliche Dinge) eben nicht wie Funktionen. Ein Statement ist eben eine Anweisung an die Sprache (bzw deren Interpreter / Compiler), aber nichts, was unmittelbar mit den zu verarbeitenden Daten / Objekten zu tun hat. Statements fallen aus der Reihe, das wollte ich damit ausdrücken.
Ich setze im folgenden mal an dass man Statements in Python und Makros in Lisp gleichsetzt, da beide eine Art Sonderstellung in den entsprechenden Sprachen gegenüber den Funktionen haben (was nicht heißt dass Makros Statements sind - es sind Expressions).

Nun, es ist eben so dass man in Python für die Arbeit mit Daten Funktionen verwendet, aber davon kann man nicht schließen dass es generell so ist. Gerade Makros Arbeiten wie Statements auf Daten (dem Code) und transformieren sie irgendwie. So gesehen bietet einem die Möglichkeit eigene Statements zu definieren einen Vorteil der grob vergleichbar damit ist welchen Vorteil es gibt, dass man eigene Typen, Objekte definieren kann. Natürlich muss man nicht OO programmieren und man muss nicht eigene "Statements" definieren können, aber es gibt einem die Flexibilität die es möglich macht. Mit Makros kann man etwa OOP in eine Sprache bringen, die kein OOP von Haus aus unterstützt. Es gibt noch mehr Einsatzzwecke, aber ich muss auch sagen, dass ich bisher selbst nicht genau weiß, was mit Makros machbar ist, was sonst zwar auch möglich aber komplizierter wäre; ich habe auch jahrelang Sprachen ohne Makros verwendet, jetzt ist es nicht ganz einfach diese zusätzliche Flexibilität an das eigene Denken einzupassen.

Eine interessante Sache die mir zu dem Thema einfällt ist, wie man in Scheme Lokigoperatoren implementieren könnte. So sind ``and`` und ``or`` Makros, da sie ihre Parameter nicht unbedingt auswerten müssen (``and bricht ab, wenn der erste Parameter False ist ab, ``or`` bricht ab wenn der erste Parameter True ist). Andererseits könnte aber ``not`` durchaus eine Funktion sein, da sie den Wert auswertet und danach negiert. Jedoch besteht in der Nutzung dieser Operatoren keinerlei Unterschied, sie verhalten sich exakt so wie ``and``, ``or`` und ``not`` in Python, die alle drei Statements sind, obwohl das ``not`` die selbe Semantik wie eine Funktion hat.

Wie sma sagte, was man als Statement rausnimmt und was man zur Expression macht ist recht arbiträr vom Designer festgelegt und wird durch dessen Ideen und auch dessen Inspirationen und Pläne bedingt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Mal ein Beispiel:

Code: Alles auswählen

def f(x, y):
    erg = x+y
    return erg

reduce(f, range(10))
Das ist ja nichts weiter als ein eigener Nachbau von operator.add, aber darum solls nicht gehen.

Der Interpreter sieht das ganze nun so, wie es ist. (bzw kompiliert, gebytekompiliert, weiß der Henker wie).
Er sieht es absolut.

Logisch gesehen ist aber folgendes zu erkennen:

Code: Alles auswählen

# Teil des Programmes.

# def: Ab hier ist es *kein* Teil des Programmes mehr
def f(x, y):
    # Eine Subroutine, dh ein eigenes Programm, Bereich ist abgeschlossen.
    erg = x + y
    # Teil des Programmes
    
    # Tätigkeit des *Interpreters* wird ausgelöst.
    return erg

# Wieder Teil des eigentlichen Programmes

# Ausführung einer Tätigkeit
reduce(f, range(10))
Was ich damit ausdrücken will: Durch Verwendung von def wird quasi ein eigenes Unterprogramm geöffnet. Das ist aus Sicht des Interpreters natürlich eine Tätigkeit. Aber für das Programm praktisch irrelevant. Ist dem Programm ja egal, ob da nun direkt lambda: x+y oder operator.add oder was auch immer steht. Oder ob man den Code zwanzigmal wiederholen muss. Das Programm würde das gleiche machen. Es ist eine Vereinfachung (Zentralisierung) durch den Interpreter, aber für die einzelnen Abschnitte des Codes macht es (außer bei eventuellen Wiederholungen) keinen Unterschied. Würde man "def" als eine Funktion betrachten, würde die Dinge tun (nämlich Funktion verfügbar machen aus einem Unterprogramm), die eigentlich nur den Interpreter was angingen, im Großen und Ganzen für das Programm aber egal sein können (sofern man es verkraften könnte, zigmal zu copy & pasten). Eine Funktion als eine Tätigkeit *im Programm* Ist nur der Funktionskörper. *Wie* der Wert nun das eigentliche Programm erreicht, ist egal. Das macht *der Interpreter*, mittel des Return Statements.
Statements tun also bei der Betrachtung Dinge, die für den Interpreter (und den genervten Programmierer) wichtig sind, aber für die eigentlichen Funktionen des Programmes nicht relevant sind (da man den Programmcode ja auch als kompletten (aber sehr großen Block) ohne Statements schreiben könnte, zb so:)

Code: Alles auswählen

a = 0
for i in xrange(10):
    a += i
Gleiches gilt hier für for, man könnte rein theoretisch auch ohne for arbeiten, indem man 10mal hinternander a+= i schreibt und zwischendrin i immer hochzählt. Das Ergebnis ist das gleiche, und so für das Programm irrelevant. Dagegen macht eben diese Codelogik an sich etwas aus, und ist auf die eine oder andere Art und Weise Teil des Programmes.
`if` und `for` sind in C *Funktionen*!? Wäre mir neu.
Öhm... Nein, aber ihr Aufruf sieht ähnlich aus, vergessen wir das lieber :oops: :D
Aber warum muss es den geben?
Weil Statements Dinge durch den Interpreter tun, aber nicht (wie Funktionen (nicht als Funktionen, aber als das Stück Programmcode, das xyz tut)) etwas für die Sprache. Es sind Zugriffe auf Features der Sprache, die aber für die reine Logik nicht existieren müssen. So meinte ich das auch mit den "Daten". Gut, heute möchte sicherlich keiner mehr Assembler schreiben, aber es würde rein theoretisch funktionieren. Die eigentliche Logik bleibt unberührt von Statements. Oder ohne Klassen arbeiten, geht heute noch recht gut. Trotzdem ist es per "class" möglich. Weil es ein Feature der Sprache ist, nicht aber, weil ein Objekt jetzt unbedingt nur Logik gehören müsste.
Es kommt zu "überflüssigem" wie dem ``a if c else b`` weil das in anderen Sprachen schon vom "normalen" `if` abgedeckt wird. Ausdrücke sind Konstrukte, die zu einem Ergebnis ausgewertet werden. Damit ist das Konstrukt per Definition ein Ausdruck. Es ist ja überhaupt nicht an Zuweisungen gebunden -- man kann es überall verwenden, wo ein Wert bzw. eben ein Ausdruck erwartet wird.
Achso, naja gut. Überflüssig habe ich übringens nur genutzt, um nicht andauerend die gleichen Wörter wiederholen zu müssen. Sowas mag ich selbst nicht gern lesen, drum wollt ichs euch ersparen.
Wieso sollte es keine Objekte geben, die "Interna" der Sprache repräsentieren? Und wieso muss man irgendwo aufhören?
Sollen nicht, klar kann man das machen. Oder man macht es anders. In Python hat man wenn man will Zugriff auf Internas. Auch lernt man mit der Zeit viele Dinge, die man eher nicht braucht oder die gut zu wissen sind, bzw schön für das Verständnis der Sprache (globals(), locals() (wobei ich das gerne in Komvination mit pdb nutze), type und dessen Verwendung zur Klassenerzeugung, ...), aber man muss nichts benutzen (oder sollte sogar nicht). Würde man das class Statement entfernen, und jeder müsste sich über type() seine Klassen erzeugen, wäre das unschön, aber möglich. Man muss nur wissen, wie Metaklassen genau funktionieren. Genauso wäre das doch mit Exceptions: Ich könnte raise verwenden *oder* eine Methode auf das Exception Objekt. Will ich aber nicht (wi wohl Io, wenn du es anmerkst, das ich bisher nicht kenne) jemanden zwanghaft mit Sprachinterna's "belästigen", kann ich auch einfach raise verwenden. Oder würdest du ernsthaft Klassen über type() erzeugen? (Wobei ich nicht bezweifle, das Methoden auf ein Exception Objekt auch eine Schöne Sache sein können)
Und in Python gibt's doch auch eine Menge (magische) Methoden, die in die Bedeutung von Statements eingreifen.
Richtig, ich könnte die aber theoretisch auch direkt aufrufen.
... man kann nur keine neue Syntax einführen.
Was auch gut so ist :D
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

str1442 hat geschrieben:Würde man das class Statement entfernen, und jeder müsste sich über type() seine Klassen erzeugen, wäre das unschön, aber möglich. Man muss nur wissen, wie Metaklassen genau funktionieren.
Nein, wieso? Es ist nur etwas weniger Syntaktischer Zucker, aber wenn ich sage dass es in meiner Sprache Klassen über ``type()`` erstellt werden und wie die Parameter zu verstehen ist, ist das überhaupt kein Problem.

Wenn ich Klassen vererbe muss ich auch nicht genau wissen wie die C3 MRO funktioniert. Ich weiß dass sie funktioniert und ich weiß wo ich nachschauen muss wenn sie nicht das tut was ich will, aber ansonsten kann ich gegeben dass wenn ich ``class SomethingElse(Something)`` das passiert was ich will.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

@str1442: Ich verstehe Dich immer noch nicht so richtig. Was willst Du mit Sätzen wie "Der Interpreter sieht das ganze nun so, wie es ist. […] Er sieht es absolut." sagen? Zumal der Interpreter den Code da nicht sieht, sondern irgend welchen Bytecode, der von der Sprachdefinition noch nicht einmal festgelegt wird.

Und mindestens die ``def``-Zeile ist Teil des ausgeführten Programms weil ``def`` in Python eine ausführbare Anweisung (Statement) ist und keine Deklaration. Die Anweisung bindet den Namen `f` an ein Funktionsobjekt, dass den Code repräsentiert. Der wird zwar erst beim Aufruf ausgeführt, ist aber sehr wohl Teil des Programms und keineswegs irrelevant. Wenn das nicht passiert könnte man den Code später nicht ausführen.

Deine beiden Beispiele kämen auch ohne die Funktionalität der Anweisungen aus, aber spätestens wenn die Obergrenze der Schleife nicht fest steht, kannst Du sie nicht so einfach durch mehrmaliges hinschreiben entfernen, weil Du ja nicht weisst wie oft Du wiederholen musst. Und ein ``if`` kannst Du schon mal gar nicht von der Programmlogik trennen.

Andererseits kann man die beiden Beispiel auch in einer Sprache ohne Anweisungen trotzdem ohne Wiederholungen im Quelltext ausdrücken:

Code: Alles auswählen

Range
f := method(x, y, x + y)
0 to(9) asList reduce(a, b, f(a, b)) println

a := 0
0 to(9) foreach(i,
    a = a + i
)
a println
Die Begründung warum es den Unterschied zwischen Anweisung und Funktionen bzw. Methoden geben muss verstehe ich wieder hinten und vorne nicht. Anweisungen tun etwas durch den Interpreter aber nicht für die Sprache!? Sprachbeschreibungen bestehen bei den meisten Sprachen mit Anweisungen in der Regel erst einmal aus den Grunddatentypen und dann den Anweisungen. Erst danach kommen die Funktionen aus der Standardbibliothek. Die Anweisungen sind wesentlicher Bestandteil der Syntax dieser Sprachen.

Assembler ist ein denkbar schlechtes Beispiel, denn das besteht ja *nur* aus Anweisungen für den in Silikon gegossenen Interpreter eine Abstraktionsschicht tiefer. Funktionen gibt's auf der Ebene ja gar nicht.

Wenn Du es auf das möglichst wenig beschränken willst (ohne bei Brainfuck zu landen), braucht man so etwas wie Funktionsaufrufe und eine bedingte Auswertung. Alles andere ist syntaktischer Zucker.

Wenn mich jemand zwingen würde mit `type()` Klassen zu erzeugen würde ich auch meutern, aber keine Statements zu haben, heisst ja nicht, dass das so umständlich sein muss.

Ich sehe auch keine "Belästigung" mit Sprachinterna, wenn ich statt ``raise Exception("blah)"`` in Io ``Exception raise("blah")`` schreiben muss. Man könnte ja genau so gut sagen dass einen Python damit "belästigt", das ``raise`` als Anweisung geschrieben werden muss.

Mal ein Io-Beispiel eines Stacks mit Datenelementen als verkettete Liste von `Node`-Objekten:

Code: Alles auswählen

#!/usr/bin/env io
EmptyStackError := Exception clone

Node := Object clone do(
    data ::= nil
    next ::= nil
    with := method(data, next, Node clone setData(data) setNext(next))
)

Stack := Object clone do(
    top ::= nil
    size ::= 0
    
    push := method(object,
        self setTop(Node with(object, self top))
        self setSize(self size + 1)
    )
    
    peek := method(
        self top ifNil(EmptyStackError raise("can't peek empty stack")) data
    )
    
    pop := method(
        node := self top
        if(node isNil,
            EmptyStackError raise("can't pop from empty stack")
        ,
            self setSize(self size - 1)
            self setTop(node next)
            node data
        )
    )
    
    asString := method(
        elements := List clone
        node := self top
        while(node isNil not,
            elements append(node data)
            node = node next
        )
        self type .. " with(" .. elements reverse join(", ") .. ")"
    )
    
    with := method(
        result := call target clone
        call evalArgs foreach(v, result push(v))
    )
)

stack := Stack clone println    # Stack with()
stack push(42) push(23) println # Stack with(42, 23)
stack peek println              # 23
stack pop println               # 23
stack pop println               # 42
try(
    stack peek println
) catch(EmptyStackError,
    "Ooops..." println          # Ooops...
) pass
Keine Anweisungen und Schlüsselworte, nur Objekte und Nachrichten, wobei Nachrichten selbst auch wieder Objekte sind. Wo wäre bei dem Quelltext jetzt etwas durch Anweisungen gewonnen? Ausser dass die Syntax der Sprache umfangreicher würde? Die informale Grammatik der gesamten Sprache sieht so aus:

Code: Alles auswählen

exp        ::= { message | terminator }
message    ::= symbol [arguments]
arguments  ::= "(" [exp [ { "," exp } ]] ")"
symbol     ::= identifier | number | string
terminator ::= "\n" | ";"
Es gibt keine `class`-"Anweisung" weil Io keine Klassen hat, aber man könnte sich natürlich auch eine `class`- und eine `def`-Methode auf `Object` definieren, die eine ähnliche "Syntax" wie Python haben, also beispielsweise:

Code: Alles auswählen

class(Foo, Object, Bar,         # "Klassenname" und Basis"klassen"
    def(methodName, arg1, arg2,
        self baz := arg1 + arg2
    )
)
Wie man sieht ist dadurch aber nicht wirklich etwas gewonnen. Nur eine leicht andere Schreibweise.
lunar

BlackJack hat geschrieben:Assembler ist ein denkbar schlechtes Beispiel, denn das besteht ja *nur* aus Anweisungen für den in Silikon gegossenen Interpreter eine Abstraktionsschicht tiefer.
Aha ... :D
Antworten