![]() |
Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Hallo liebe Delphisten,
im Laufe der Zeit haben sich bei mir einige Dinge angehäuft, die mich an der aktuellen Syntax von Object Pascal stören. Darunter sind folgende:
Daher habe ich mir mal einen Entwurf für einen neuen kleinen Dialekt überlegt, der diese Dinge besser machen soll, ich nenne ihn bisher "Thrym". Hier mal ein Ausschnitt:
Delphi-Quellcode:
Nun möchte ich das ganze aber nicht einfach verschlimmbessern, daher Frage an euch: Was haltet ihr von diesen Änderungen, insbesondere dem automatischen nil-setzen?
// Thrym
unit sample; // Uses-Klausel außerhalb von public/private/implementation uses ... // public + private statt interface public type TExample = class public procedure Sample; end; // Counted Interfaces: // Klassische COM-Interfaces, auf Methoden beschränkt, // Properties gehen den Weg über diese // (Referenzzählung!!) IExample = counted interface ['{GUID}'] procedure SetTest(AValue: Integer); function GetTest: Integer; property Test: Integer read GetTest write SetTest; end; // Uncounted Interfaces: // Von COM komplett unabhängig, keine Referenzzählung // Properties müssen nicht direkt einen Getter/Setter // zugewiesen bekommen, dies ist Sache der Implementierung // Implementierende Klassen müssen nicht AddRef/Release/ // QueryInterface unterstützen ISample = uncounted interface property Test: Integer read write; end; ... const ... var ... private type // Schema-Typ, wie in GPC: TCharArray(start, length: Integer) = array [start..start+length] of char; TSample = TCharArray(0,6); ... const ... var ... FProp: Integer; // können auch mehrere public/private sections sein public // z.B. um global properties besser zum ermöglichen property Prop: Integer read FProp write FProp; implementation // oh, it's me! // In den Implementation-Teil kommt // tatsächlich nur noch die Implementierung // der im public- und private-Teil deklarierten // Methoden und nichtmethodischen Routinen // Methoden gruppieren nach Klasse TExample: begin procedure Sample; var obj: TExampleObject; begin obj := TExampleObject.Create; try // Do Something finally // den Destruktor gefahrenlos direkt aufrufen können // damit benannte Destruktoren auch endlich wieder Sinn // machen - wozu kann man sonst mehrere Destruktoren // deklarieren, wenn man eh nur Destroy über Free verwenden // kann obj.Destroy; // schön wäre es jetzt noch, wenn obj gleich auf Nil gesetzt würde // dazu aber dick: Fragezeichen ? end end; end; end. Je nach Feedback setze ich das ganze vllt. in Zukunft mal durch einen Präcompiler um, der dies dann in FreePascal-Code oder Delphi-Code umschreibt. Verbesserungsvorschläge, Kritiken und Featurerequests sind gern willkommen (dazu mache ich den Thread ja auf :stupid:) |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Es mag verschiedene Arten geben ein Objekt zu erzeugen aber es gibt nur eine Art es zu zerstören. Das gilt IMHO für alle OO Programmiersprachen. In Delpi muss der Destruktor immer so deklariert werden:
Delphi-Quellcode:
Jeder Abweichung von dieser Deklaration führt zu einem nicht funktionierenden Destruktor.
destructor Destroy;override;
|
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Danke schonmal für dein Feedback!
Zitat:
Was ist, wenn ich eine Objektliste deklarieren will, und zwei verschiedene Destruktoren möchte: Einer, die die Objekte mitfreigibt, und einer, der dies nicht tut. Momentan wäre das auf diese Weise so nicht wirklich machbar. Wir haben in Object Pascal benannte Destruktoren, wir können sie nur nicht anständig nutzen. Und das stört mich, deshalb möchte ich es in Thrym besser machen. Zitat:
|
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Das Problem von Delphi ist, dass der Destruktor überhaupt einen Namen bekommen hat. Man hätte das z.B. auch so machen können:
Delphi-Quellcode:
TEineKLasse = class(TBasisKlasse)
... public constructor Create; destructor; end; destructor TEineKLasse; begin ... inherited; end; // und statt Destroy oder Free würden man Objekte so freigeben: Dispose(einObjekt); |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Genau, so habe ich mir das zunächst auch gedacht, als mir das Problem bewusst wurde.
Aber warum nicht den "Bug" zum Feature machen ;) Im oben erwähnten Beispiel mit der Objektliste hielte ich es für sehr sinnvoll, zwei verschiedene Destruktoren zu haben. Das zweite Destruktor-Problem ist, dass man ihn nicht direkt aufrufen sollte, weil's Crash geben kann. Und was macht man da? Dem Destruktor die gleiche Funktionalität der Free-Methode geben, ist mein bisheriger Vorschlag. [EDIT] Ah, jetzt erst das Dispose bei dir gesehen. Das ist auch ein sehr guter Vorschlag, da hätte man es gleich einheitlich mit Pointern. |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Das fällt mir jetzt spontan so ein... |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Ansonsten ist Delphi leider veraltet und hinkt. Das Handicap wird es auch nicht wieder los. |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
|
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Delphi-Quellcode:
Sieht einfach nur häßlich aus und paßt nicht zur Pascal/Delphi-Syntax.
TCharArray(start, length: Integer) = array [start..start+length] of char;
TSample = TCharArray(0,6); Was ich mir aber wünschen würde: - die Generics so erweitern, daß man statt typen auch Konstanten verwenden kann. (würde dann teilweise ähnliche Möglichkeiten bieten, wie die Makros in C) - ein mehrstufiger Compiler, bzw. ein intelligenterer, so daß man besseren Zugriff auf die Typen hat, welche im denerischen Type enthalten sind. - generische Prozeduren, Interfaces und Class Helper (nicht nur Klassen.Methoden) - Class Helper Record Helper für einfache Basistypen, wie t.B. den Integer oder den String - Interface Helper - Operatoren für Interfaces - Operatoren für Copy, Create und Destroy von Records (technisch leicht möglich, da alle Struckturen schon existieren ... siehe Behandlung der Interfaces, dyn. Arrays und der Strings innerhalb von Records) - endlich mal ein Versesserung einiger Grenzen in der OTA (jbg bekommt auch immer wieder mit, daß Vieles einfach nur fehlt oder schecklich implementiert ist) - und ein OTA-Interface für einen eigenen Precompiler - daß man bei dyn. Arrays das CopyOnWrite aktivieren kann, so wie es bei den Strings auch vorhanden ist - ein Continue und Break mit Ebenenangabe, so daß man mehrere Schleifen unterbrechen kann - manchmal (ganz selten) hab ich mit schon eine kombinierte Try-Except-Finally-Stuktur gewünscht - ![]() - string aus den reservierten Wörtern rausnehmen - ein "caseend" für die varianten Recordteile ("end" geht ja nicht mehr ... das hätte man gleich zu Beginn nicht vergessen dürfen :wall:) - das Strg+Linksklick auf einen generischen Teil (Methode,Feld,...) nicht bei "implementation" landet, sondern beim generischen Typen :roll: - uvm. Also nur Neuerungen/Verbesserungen, welche aber nicht die "alte" gewohnte Syntax beeinflussen - eine bessere Informationspolitik seitens Emba, endlich mal eine ordentliche Emba-Webseite erwähn ich besser mal nicht :stupid: Zitat:
Das zu den störenden Elementen und wenn, dann darf man das gerne auch in einer neuen Syntax verbauen. |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Na das sind ja schonmal einige Punkte :thumb:
Zitat:
Zitat:
Delphi-Quellcode:
TIrgendwas<type t; const a,b: Integer> = class
... end; Zitat:
Delphi-Quellcode:
TXyz = helper for ...
... end; Zitat:
Delphi-Quellcode:
operator :=(const i: IMyInterface): string;
Zitat:
Zu allem unkommentierten: Full Ack :thumb: |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Delphi-Quellcode:
, für jeden Typ, egal ob Klasse, Record oder primitiver Datentyp wie Integer. Diese Unterscheidung von class helpern und record helpern ist redundant, weil der Datentyp, auf den sich der Helper bezieht, ja ohnehin klar ist. Und falls man mal aus einem Record eine Klasse macht oder umgekehrt, müsste man nicht auch noch zusätzlich alle Helper-Definitionen anpassen.
Helper
Delphi-Quellcode:
Damit wären sehr moderne Konstrukte und modulare Programmierung möglich.
type
TFormHelper = helper for TForm procedure FadeOut(); end; TRectHelper = helper for TRect procedure Normalize; function ContainsPoint(Pt: TPoint): Boolean; end; TIntHelper = helper for Integer function ToString: string; end; |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Aber dann wäre es nicht mehr ganz kompatibel zum alten Code. Zitat:
Für Objekte sind Operatoren leider nicht möglich, der fehlenden automatischen Speicherverwaltung wegen, aber wenn man die Copy/Create/Destroy-Ereignisse einführt, würde es dennoch einen Weg geben. :angle: |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Mein Wunsch geht zwar über Syntax hinaus, und dafür würden mich sicher hier gerne einige vermöbeln, aber ein Delphi mit GC wäre schon sexy. Ich weiss, es gibt da diverse Fummelein mit Interfaces und Hacks, aber ein richtiger "ab Werk" GC ist einfach eine riesen Komfortsteigerung (wenn er vernünftig umgesetzt ist). Was ich in C# ab und an gern mache, und in Delphi ab und an wünschte, ist sowas wie
Delphi-Quellcode:
, und die Instanz dann einfach verpuffen lassen. (Ja, das sieht nach einem Designfehler aus, man meint die Methode hätte statisch sein sollen - aber so schlau sind leider nicht alle Fremdkomponentenhersteller.) Oder auch so Späße, bei denen Instanzen über mehrere Threads eher "locker umher geworfen" werden würden mit einem GC etwas weniger Kopfschmerzlastig.
lokaleVarMitRückgabewert := TMyFooClass.Create(aParameter).SomeMethod(aNotherParameter);
Vielleicht sogar als alternativer Konstruktor, ggf. mit Einführung des new-Operators!
Delphi-Quellcode:
Mit etwas Unterstützung in der IDE (anderes Highlighting für GC'ed Instanzvariablen) wäre so ein Hybrid glaube ich sogar einigermaßen handlich.
bar := TMyFooClass.Create(); // <- normal ohne GC
bar := new TMyFooClass(); // <- GC'ed |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
@Medium:
Das ist eine verdammt gute Idee! Was mich an GC-Sprachen bisher insbesondere gestört hat, war, dass man den GC nicht einfach abstellen konnte. Ich habe über eine Hybridschiene schon nachgedacht, aber da bin ich immer zur Kollision gekommen. Der Einfall, die Objekte einfach durch einen anderen Konstruktor zu erzeugen ist ein genialer Ansatz. Das wäre allerdings ein Punkt, den ich allein nicht umsetzen könnte, weil ich a) von GC-Bau keinen Schimmer habe und b) auch keinen kenne, den man zu dem Zweck in die Ausgabedatei einfach automatisch einbinden könnte. Die bisherigen Punkte würde ich mir zutrauen, aber ein Hybrid-GC ginge über meine Fähigkeiten hinaus. |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Ansonsten hast du ein Problem, da plötzlich aus Diesem ein "reserviertes" Wort werden würde. In Delphi also nicht möglich, obwohl es auch ohne GC technisch möglich wäre, wenn man den "new"-Operator auf die ".Create"-Constructoren umleitet. Wenn man Klassen direkt als Interface markieren könnte, bei deren Deklaration, ohne vorher einen extra Interface-Typen manuell deklarieren zu müssen (der Compiler würde dann aus den Public/Published-Dingen dass Interface automatisch generieren), dann hätte man quasi auch einen GC für diese Objekte. (über die Technik der Generics eventuell machbar, also wenn Emba das implementiert) Über einen Precompiler könnte ich sowas auch selber nachrüsten. :stupid: |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Mich würde jetzt auch mal genauer interessieren, was ihr von der Unit-Umstellung von Interface/Implementation auf Public/Private/Implementation haltet. Stimmt ihr mir zu oder haltet ihr das für überflüssig?
Was haltet ihr von der Methodengruppierung? |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Zitat:
Grüße |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Im Prinzip eigentlich nicht notwendig.
Interface = Public Implementation = Private Protected gibt's da nicht, bzw. es ist sinnlos, da die Vererbung fehlt und es somit dem Private entspricht. Das Property ohne Klasse könnte nett sein, für globale Variablen oder Singletons. Aber da man solche Globalen sowieso besser vermeiden sollte, bringt es eigentlich nicht viel. Die Methodengruppierung finde ich unübersichtlich. Seh ich irgendwo in der Implementation ein
Delphi-Quellcode:
, dann denke ich das wäre eine Prozedur und nicht daß sich da irgendwo noch ein
procedure irgendwas;
Delphi-Quellcode:
verstecken könnte, welches dieses zu einer Methode macht.
begin
Zwei Klassen, mit einer gleichnamigen Methode, dann stehen unten zwei Prozeduren, welche man nicht direkt einer der Klassen zuordnen kann, ohne vorher nach einem "begin" zu suchen, um zu sehn ob und wenn ja zu welcher Klasse es gehört. |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Zitat:
nichtmethodische Routinen = Prozeduren und Funktionen, die keiner Klasse angehören
Delphi-Quellcode:
Wie die Gruppierung aussehen soll, steht nicht fest (wie allgemein noch nichts), im Entwurf im oberen Post sah sie so aus:
procedure TXyz.DoSmthng; // Methode
function IntToStr(AValue: Integer): string; // keine Methode
Delphi-Quellcode:
implementation
TXyz: begin procedure Xyz; begin // Do something end; end; end. Zitat:
Zitat:
Zitat:
|
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Dieser Operator ist ein Makel, den fast alle Sprachen von C erben. Ich finde es semantisch viel schöner, wenn der Konstruktor wie eine klassenstatische Methode ist, die eine Instanz zurückliefert. Die Klasse selbst ist für die Erzeugung ihrer Instanzen zuständig. Ist das nicht wunderschön OO? :love: |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Von mir aus dann eben TMyClass.CreateManaged() oooder in TObject bereits einen Parameter einführen: TObject.Create(isManaged: Boolean); :P
Letztlich gehopst wie gesprungen, wobei ich die syntaktische Unschönheit von new nachfühlen kann. Die Alternative mit Parameter oder Benamung hätte nur ggf. den Nachteil, dass man die Eindeutigkeit in Ableitungen sehr leicht (und fahrlässig) verschleiern könnte, und man es der IDE beim Unterscheiden zusätzlich schwer machen würde. (Sie müsste schon regelrechte Interpreterfähigkeiten bekommen, aber vielleicht wäre das ja mal ein Anreiz die IDE-Features mehr an den Compiler zu knurpseln als z.B. das dolle ErrorInsight oder wie sich die vielen falschen roten Unterwellungen schimpfen, die scheinbar eher selten Plan von der Projektstruktur haben.) Oder, wobei ich das so garnicht mag: Annotations. Wobei diese dann in die Klassendeklaration gehörten, und somit die GC-Bindung nur per Klasse (und all ihrer Nachfahren) gegeben wäre, und man nicht die Freiheit hätte von Instanz zu Instanz zu unterscheiden. Eher bäh. |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Drum meinte ich ja, im Falle von
Delphi-Quellcode:
würde der Compiler dann Standard-Constructor "Create" aufrufen, sich einen Suchen, welche den übergebenen Parametern entspricht, falls es diesen gibt und am Ende es zu einem
bar := new TMyFooClass();
Delphi-Quellcode:
umwandeln.
bar := TMyFooClass.Create();
Und schon wäre das OOP-Prinzip gewahrt. Nur wird es eben schwer einen neues "reserviertes Wort" einzuführen. Das ist wohl auch der Grund, warum es "Class Helper" und nicht nur "Helper" heißt, da durch das reservierte "Class" das Helper geschützt/eingeleitet wird, womit die Syntax dennoch kompatibel bleibt. Wenn man eine Syntax von Grund auf neu baut, könnte man z.B. NEW gleich reservieren. Mit den großen Neuerungen und vielen Änderungen seitens D2009/XE2 hätte man diesbezüglich schnell noch ein paar neue "reservierte" Wörter mit einführen und alte Makel in der Syntax ausbessern können. Wenn sowieso genug angepaßt werden muß, dann kommt es auf die paar Änderungen auch nicht mehr an. :twisted: Sowas wäre syntaktisch möglich:
Delphi-Quellcode:
genauso wie ja auch sowas gehn:
type
TMyClass = class managed(Txyz) end;
Delphi-Quellcode:
type
TMyClass = class sealed(Txyz) end; TMyClass = class abstract(Txyz) end; |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
So... es wird Zeit, dass ich mich auch mal in diese Diskussion einmische. :mrgreen:
Zitat:
Delphi-Quellcode:
oder Pointer auf Records)), anderseits arbeiten "Unit basierte" Compiler wie FPC und Delphi so, dass sie sich beim Kompilieren einer weiteren Unit erst nur den Interface Teil der Unit anschauen müssen, um festzustellen, ob sich was geändert hat und demnach die erste Unit neukompiliert werden muss. Wenn du nun Teile des Implementationbereichs in den Interfacebereich schiebst, so muss der Compiler auch über diese Teile hinweg parsen, selbst wenn er sie eventuell gar nicht benötigt, weil sich nichts geändert hat.
forward
Ganz davon abgesehen ist das mit Interface und Implementation Anfängern einfacher zu erklären als "also wenn du da jetzt noch auf eine private Variable der Unit zugreifen möchtest, dann musst du vor diesem Public Abschnitt noch einen Private Abschnitt einfügen" Zitat:
Nichtsdestotrotz: Free Pascal unterstützt nicht-referenzgezählte Interfaces (so genannte CORBA Interfaces). Die kannst du (per Unit oder eventuell sogar lokal per Deklaration, das weiß ich grade nicht) ganz einfach per "{$interfaces corba}" aktivieren. Du deklarierst dann ganz einfach dein Interface, diese leiten dann jedoch NICHT von IInterface/IUnknown ab (um genau zu sein haben die dann gar keinen Vorfahrn) und benötigen auch keine Implementierungen für QueryInterface, AddRef und Release. Seit FPC 2.4.0 funktionieren die sogar ähnlich wie COM Interfaces hinsichtlich "as" und so (aber eben ohne Referenzzählung). Zu deinem a): Dies wäre ein Feature, dem ich eventuell sogar eine gewisse Sinnhaftigkeit zugestehen könnte (ich arbeite nur selten mit Interfaces, deswegen...). Solche Interfaces kannst du dann natürlich nur in Pascal Code einsetzen, da zum Beispiel ein C++ Code, welcher dieses Interface verwendet, nicht wissen kann wie er auf die Property zugreift (außer man streut hier sehr viel Compilermagic ein...) Zu deinem b): Das Problem hierbei ist die Referenzzählung. Delphi und FPC fügen nur Code zum Ändern der Referenzzählung ein, wenn es sich um eine Interface Referenz handelt. Also rein prinzipiell könntest du sie sogar mischen, wenn du manuell mit AddRef und Release auf der Objektreferenz arbeitest... (nicht dass das unbedingt das sinnvollste ist, aber es würde gehen) Falls du dich jedoch darauf beziehst, dass du einer Objektreferenz keine Interfacereferenz zuweisen kannst, dann hat das den Hintergrund, dass ein Interface ja von unterschiedlichen Klassen implementiert werden kann. Diese Klassen müssen dabei ja nichteinmal verwandt sein. Also eine automatische Konvertierung würde ich da gar nicht wollen. AFAIK unterstützen jedoch modernere Delphi Versionen (XE+?) ein "as", um von Interfaces auf Objekte zu casten und wenn das nicht geht wird eine Exception geworfen (wie von "as" gewohnt). Vielleicht gibt es da auch ein "is", das weiß ich gerade nicht. Das wären auf jeden Fall zwei Features, die zu FPC hinzugefügt werden könnten/sollten. Zitat:
[QOUTE][*]Man kann zwar mehrere verschiedene benannte Destruktoren deklarieren, das hilft aber nichts, weil Free immer nur einen ganz bestimmten aufruft. Wozu haben wir denn unser schönes Benennungsfeature?[/LIST] Und es funktioniert auch wie es soll. "Free" ist nur eine normale Prozedur deren einziger Sinn es ist zu überprüfen, ob "Self <> Nil" ist und dann den Default-Destruktor "Destroy" aufruft. Nichts hält mich davon ab einen Destruktor mit einem anderen Namen zu definieren und einfach direkt aufzurufen. Es ist nämlich der Aufruf des Destruktors, der die Speicherfreigabe veranlasst, nicht der von Free (sonst bräuchten wir ja kein spezielles Keyword für den Destruktor).
Delphi-Quellcode:
Schematypen stehen bei mindestens einem FPC-Entwickler auf der Wunschliste.
type
// Schema-Typ, wie in GPC: TCharArray(start, length: Integer) = array [start..start+length] of char; TSample = TCharArray(0,6); Weil's grad zum Kontext passt noch der Einwurf Himitsus dazu: Zitat:
Zitat:
Delphi-Quellcode:
Der Compiler muss den Punkt "TTest<5" nun irgendwie intelligent behandeln. Es kann vielleicht schaffbar sein, aber wenn ich mir allein den Code anschau, den ich geschrieben habe, um die Inlinespezialisierung "TTest<SomeType>" zu erlauben, dann möchte ich nicht wissen, was ich da alles verbrechen muss (und dabei hab ich es noch nichteinmal geschafft die Überladung mit einer Variable zu implementieren, das steht noch auf meiner ToDo Liste, weil's (hoffentlich) ein extremes Randbeispiel ist).
type
TTest<const c> = class end; var TTest: Integer; // was ja erlaubt ist in Delphi! (in FPC funktioniert das noch nicht...) begin if TTest<5>.Irgendwas then ... end. Zitat:
Zitat:
Delphi-Quellcode:
type
TSomeClassHelper<T> = class helper for TObject function ReturnDefault: T; // mir fällt grad nichts besseres ein end; function TSomeClassHelper.ReturnDefault; begin Result := Default(T); end; type TSomeClassHelperInteger = TSomeClassHelper<Integer>; var i: Integer; ... i := SomeObject.ReturnDefault; ... Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
sollte es doch tun, oder nicht?
&String
Zitat:
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
Dass ich da Klammern setzen muss, hat mich schon immer aufgeregt...
if not (SomeEnum in SomeSet) then
// vs if not SomeEnum in SomeSet then Zitat:
Delphi-Quellcode:
fusst darauf, dass genau das eben nicht geht!
if TSomeGeneric<SomeType>.BlaBla
Zitat:
![]() Zitat:
Zitat:
Delphi-Quellcode:
Wie gut das funktionieren würde, wenn man Objekte über Prozeduren hinweg reicht, weiß ich noch nicht, aber es wäre vielleicht eine Idee...
var
bar: TMyFooClass autoref; begin bar := TMyFooClass.Create; ... // bar wird automatisch freigegeben, falls keine Referenz darauf mehr existiert (die Überprüfung hierzu ist jedoch schwierig) end; Zitat:
Delphi-Quellcode:
type
TSomeRefCountedObject = class refcounted (TParentClass) // in dieser Reihenfolge, um analog zu "sealed" und "abstract" zu sein end; Zitat:
Und was ich mir wünsche (und vielleicht auch mal implementieren werde):
So... Ende der langen Liste :P Gruß, Sven |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
|
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Zitat:
Zitat:
Zitat:
Gruß, Sven |
Dieses Thema wurde am "12. Jan 2012, 17:07 Uhr" von "TBx" aus dem Forum "Programmieren allgemein" in das Forum "Software-Projekte der Mitglieder" verschoben.
|
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Auch wenn man jetzt das IN vorrangig behandeln würde, wäre das keine Lösung, da sich dann Andere wieder beschweren würden, weil plötzlich was Anderes nicht mehr ginge. Zitat:
Ich weiß nichtmal, warum man STRING so behandeln mußte? Und wenn, warum ist dann Integer, Boolean und Co. nicht auch fett? :gruebel: Zitat:
Zitat:
Delphi-Quellcode:
In diesen schon vorhandenen Funktionen muß man nur noch schauen, ob in der RTTI des Records die neuen Operatoren stehen und ruft sie dann auf.
var
X, Y: TMyRecord; begin << X und Y werden initialisiert (wenn dort bestimmte Typen drauf sind) Y := X; << es wird eine Kopierfunktion aufgerufen, welche den Record kopiert end; << es wird eine Funktion aufgerufen, welche den Record freigibt Es gibt schon seit langem einen EDN.Eintrag von mir, aber auf mich hört ja keiner. (vorallem da es keine großen Änderungen mit sich zieht) |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Die Bitweisen möchte man halt gerne stark binden und die Booleschen schwach. Intuitiv würde ich aber auch eher immer annehmen, das ein boolescher Operator gemeint ist. Wer mit bitweisen Operatoren werkelt, kann auch ein paar Klammern mehr vertragen :wink: Oder wie wäre es mit lnot, land, lor :stupid: |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Zitat:
Delphi-Quellcode:
type
String42 = String[42]; Zitat:
Zitat:
Diese Ereignisse wären aber durchaus interessant, das müsste ich mir mal im FPC anschauen, was man da machen könnte. Gruß, Sven |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Das traurige ist ja, dass entsprechende Funktionen zum Finalisieren von Records und Arrays ja bereits vorhanden sind – sieht man auch im Assembler-Code. Nur leider gibt es keine Möglichkeit, sich dort einzuklinken. |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Eine Möglichkeit gäbe es.
Die System.pas verändern, neu kompilieren und dann auch noch alle BPLs neu kompilieren. Statt einem Operator könnte man Klassenmethoden verwenden, welche jeweils einen vorgegebenen Namen und bestimmte Parameter haben müßten. Aber vorallem das Ändern der System.pas und vorallem der BPLs, ist nicht grade optimal schön. |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
|
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Hab ich auch gedacht, aber mit ein paar speziellen Parametern (Einstellungen) seitens des Compilers, soll es möglich sein.
Denn Records haben, vorallem im Zusammenhang mit Mathematikbibliotheken, einige Vorteile. Objekte => garkeine automatische Speicherverwaltung, der Objektvariable Interfaces => automatische Freigabe, wenn der letzte Weg ist Records => automatische Speicherreservierung, Freigabe für jede Variable einzeln, Umkopieren bei Variablenzuweisung usw. |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Wahrscheinlich (ich werde für den Delphi Compiler jedoch keine Hand ins Feuer legen) wird diese geänderte System.pas aber nur funktionieren, wenn das Record auch Felder von "managed" Typen wie Strings, Arrays oder Interfaces enthält. Ansonsten wird sich der Compiler wahrscheinlich denken: "och, da muss ich nichts machen, also machen wir ein einfaches "Verringern des Stackpointers" (Speicherplatz belegen), "Move" (Zuweisung), "Erhöhen des Stackpointers" (Speicherfreigabe, wobei das auch meist durch ein "ret" abgedeckt wird).
Für FPC muss ich erst nachschauen, was der bei Records mit "managed" Feldern überhaupt aufruft :) Ein wichtiger Punkt ist bei diesem Feature jedoch dabei: ein RTTI Lookup für die "Ereignisbehandlungsroutine" ist relativ aufwendig. Wenn dies also bei jedem Record gemacht wird, dann wird es relativ teuer Records zu verwenden (dann muss man fast schon zu den guten, alten Objects greifen, wenn man den Overhead vermeiden möchte :P ). Gruß, Sven |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Ich hätte gern Mehrfachvererbung für Interfaces:
Delphi-Quellcode:
Mehrere Class-Helper sollten sich für eine Klasse nicht gegenseitig ausschließen.
type
MyInterface3 = interface(MyInterface1, MyInterface2) end; var v1: MyInterface1; v2: MyInterface2; v3: MyInterface3; begin v1 := v3; v2 := v3; |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Jupp, und auch deshalb muß es direkt von Embarcadero implementiert werden, dann dort könnte man diese Optimierung dann anpassen und auch ein ordentlicher Operator wäre dann möglich/vorhanden.
Mehrfachvererbung geht nunmal nicht. Aus dem selben Grund, warum es auch bei Klassen nicht geht. Bei den "einfachen" Interfaces werden die Methoden über einen Index aufgerufen. Bei Interface-Vererbung baut das neue Interface auf das alte auf, also es wird weitergezählt und weiterzählen ist nur für einem Vorfahren möglich, bzw. es können keine Indize mehrfach belegt sein, was bei mehrere Vorfahren aber zutreffen würde. Für gewisse COM-Interfaces, wo die Methoden über einen Namen aufgerufen würden, würde es theoretisch gehen, aber da die Möglichkeit von gleichen Namen bestünde, ist das also unsicher und somit besser ganz ausgeschlossen. |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Zitat:
Delphi-Quellcode:
Selbst wenn beide Interfaces auf die selben Methoden verweisen würden, ist dies kein Problem.
type
TMyClass = class(TObject, MyInterface1, MyInterface2) end; Der Compiler müsste für die Realisierung der Mehrfachvererbung bei der Prüfung von Zuweisungen die doppelte Vererbung berücksichtigen und an dieser Stelle ein "QueryInterface" einfügen. |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Das ist aber keine Mehrfachverwebung.
Es wird nur von TObject geerbt. Die Interfaces werden nur implementiert. Das eine Objekt wird mit mehreren Interfaces verbunden, was natürlich geht, aber wenn man sich einen Interfacezeiger von diesem Objekt holt, dann zeigt der immer nur auf jeweils eines der möglichen Interfaces. Das hier ist eine Interfacevererbung (ein Interface erbt von einem anderem Interface):
Delphi-Quellcode:
Objekte erben nur von Objekten und Interfaces nur von Interfaces ... eine Vermischung der Rassen tritt nicht ein.
type
IMyIntertface = interface(IOtherInterface) [MyGUID] ... end; |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Ich wollte nur zeigen was bisher möglich ist und wie der Compiler arbeiten müsste, um Mehrfachvererbung zu ermöglichen. Natürlich ist intern eine Sonderbehandlung durch den Compiler notwendig. Im Detail stelle ich mir das ungefähr so vor:
Delphi-Quellcode:
type
MyInterface1 = interface procedure My1; procedure MyX; procedure MyY; end; MyInterface2 = interface procedure My2; procedure MyX; procedure MyY(AValue: Integer); end; MyInterface3 = interface(MyInterface1, MyInterface2) // Compiler-Magie -> MyInterface3 = interface() // automatisch unsichtbar hinzugefügt -> procedure My1; // aus MyInterface1 procedure MyX; // aus MyInterface1, MyInterface2 -> nur einmal da eindeutig procedure MyY; overload; // aus MyInterface1, andere Parameter procedure My2; // aus MyInterface2 procedure MyY(AValue: Integer); overload; // aus MyInterface2, andere Parameter // vom Entwickler neu definiert -> procedure MyZ; end; TMyObject = class(TInterfacedObject, MyInterface3) // automatisch durch den Compiler hinzugefügt: MyInterface1, MyInterface2 procedure My1; procedure MyX; procedure MyY; overload; procedure My2; procedure MyY(AValue: Integer); overload; procedure MyZ; end; var v1: MyInterface1; v2: MyInterface2; v3: MyInterface3; begin v1 := v3; // Compiler erkennt Mehrfachvererbung -> v3.QueryInterface(MyInterface1, v1); v2 := v3; // Compiler erkennt Mehrfachvererbung -> v3.QueryInterface(MyInterface2, v2); |
AW: Störende Elemente der Delphi-Syntax / Vorschläge für neuen Dialekt
Und das ist bei den normalen/einfachen Interfaces falsch, denn es geht nicht um Methodennamen ... diese sind vollkommen egal.
Delphi-Quellcode:
Beim Objekt verlinkt der Compiler nun die Interfaces und hinterlegt, bei den Methodenlisten er Interfaces, die Zeiger zu den jeweiligen Methoden.
MyInterface1 = interface
procedure My1; // Methode 1 (Index 0) procedure MyX; // Methode 2 (Index 1) procedure MyY; // Methode 3 (Index 2) end; MyInterface2 = interface procedure My2; // Methode 1 (Index 0) procedure MyX; // Methode 2 (Index 1) procedure MyY(AValue: Integer); // Methode 3 (Index 1) end; Will man nun mehrere Interfaces vererben, dann müßten im abgeleiteten Interface nun jeweiles mehere Methoden zu einem Index hinterlegt werden, was natürlich nicht geht. Auch den Indize verschieben geht nicht, da es dann nicht mehr zum Vorfahren paßt. Selbst wenn nur die Indize hinereinander gelegt würden, also die Indize des zweiten Interfaces werden verschoben, ohne daß das Vorfahreninterface wirklich "implementiert" würde, also quasi der Vorfahre wird nur als Vorlage verwendet, wäre das keine sichere Methode, denn wenn man den Vorfahren verändert, würde das eigene Interface verändert. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:11 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz