Brainstorming Programmiersprache

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Brainstorming Programmiersprache

Beitrag von BeRsErKeR »

Hallo liebe ZFX-Developia-Community,

wie in diesem Thread angesprochen, möchte ich hiermit alle aufrufen mal einige Gedanken, Ideen, Anregungen und Vorschläge zum Thema "Neue Programmiersprache" niederzuschreiben.

Ich gebe hier mal ein paar Themen vor, die mich zum Beispiel interessieren, aber jeder kann natürlich weitere Themen ansprechen. Damit das ganze übersichtlich bleibt bitte ich um folgende Dinge:

1. Bitte lasst das Thema nicht in einen Dialog ausarten oder vom Thema zu sehr abschweifen (z.B. Welche-Programmiersprache-ist-die-Beste-Diskussionen).
2. Bezieht euch bitte immer auf Themenpunkte. Vielleicht immer den jeweiligen Abschnitt mit fetter oder unterstrichener Überschrift beginnen, die sagt um was es geht. Wie gesagt könnt ihr auch neue Themen ansprechen.

Was ist das Ziel?

Das Ziel ist zunächst der Austausch von Know-How und Ideen im Bezug auf eine mögliche neue Programmiersprache. Ob diese jemals umgesetzt wird sei einmal dahingestellt. Aber ich denke jeder kann von dem Wissen aller profitieren. Und vielleicht wird ja irgendwann sogar mal ein ernstes Projekt draus.

Um es etwas zu präzisieren: Es soll darüber diskutiert werden, was man in einer neuen Programmiersprache besser machen könnte im Vergleich zu bestehenden. Oder aber welche neuen Features man noch hinzunehmen könnte. Auch Entscheidungsfragen wie "Mit oder ohne Garbage Collection" usw. sind natürlich erwünschenswert. Das ganze sollte aber sachlich bleiben und jeder sollte auch seine Sichtweisen begründen und die Meinungen anderer respektieren. Also bitte keine Glaubenskriege lostreten.

Vorauswahl Themen:
  1. Welche Paradigmen und vorallem welche Art Programmiersprache (imperativ, funktional, was ganz anderes)
  2. Reduktion von Nebenwirkungen (z.B. pure Funktionen)
  3. Konventionen für Namen (Datentypen, Bezeichner, Schlüsselwörter, usw)
  4. Klassenkonzept (Interfaces, Vererbung, Polymorphie, Daten außerhalb von Klassen möglich, usw)
  5. Templates, Variadic Templates/Parameter, Macros, Präprozessor, usw
  6. Interpretierbar oder kompilierbar, Zwischen- bzw. Zielsprache, VM, usw
  7. Speichermanagement (statisch, dynamisch, Garbage Collector, usw)
  8. Support für Prozesse, Threads, parallele Verarbeitung, verteilte Systeme/Applikationen, usw
  9. Syntaxvorschläge, Einrückungen als Sprachmittel, Operatoren und deren Überladung, Schlüsselwörter, usw
  10. Zugriff auf I/O-Daten (separat von Sprache, Streams, Netzwerkdaten, Pipes, usw)
  11. Funktionszeiger, Delegaten (eigene Datentypen?, überhaupt notwendig/unterstützt?)
  12. Closures, Lambda-Expressions, usw
  13. Grundlegende Sprachkonstrukte wie Verzweigungen, Schleifen usw.
  14. Exception-Handling, Assertions, Debugging
  15. Zeichen und Zeichenketten (Teil der Sprache?, Encodings, Literale)
  16. Arrays (1-dimensionale, n-dimensionale) und Zeiger
  17. Referenzen, const, lvalues, rvalues, usw
  18. Modulkonzept, Namensräume, Scope, Deklarationsreihenfolge, usw
  19. Alias- und Ersetzungskonstrukte wie using, alias, typedef, auto
  20. Type-Traits/Builtin-Funktionen: z.B. int.size(), float.nan oder int.parse(string)
Die Frage ist ob und in welchem Umfang die angesprochenen Themen umgesetzt werden sollen, aber auch in welcher Form. Interessant fände ich auch wie wichtig ihr bestimmte Dinge einschätzt. Auch wichtig ist ob bestimmte Dinge Teil der Sprache sein soll oder vielleicht Teil einer Library. Es geht hier auch in gewisser Weise um deren späteren Anwendbarkeit, daher sind auch Themen aufgeführt, die eventuell nicht Teil der Sprache, sondern einer Library sind, bei der man aber schon im Voraus eventuell bestimmte Dinge im Sprachdesign berücksichtigen sollte.
Zuletzt geändert von BeRsErKeR am 21.06.2012, 13:05, insgesamt 2-mal geändert.
Ohne Input kein Output.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Brainstorming Programmiersprache

Beitrag von BeRsErKeR »

Ich mach gleich mal den Anfang:

A. Alias- und Ersetzungskonstrukte wie using, alias, typedef, auto

Ich bin eigentlich gegen solche Konstrukte. Sie verkürzen zwar den Code und verringern die Schreibarbeit, aber in vielen Fällen, führt es auch zur Verschleierung und zu Doppeldeutigkeiten. Als Beispiel:

Code: Alles auswählen

typedef int Index;
void foo(int x);
void foo(Index x);
Auch ein using namespace kann vieles verkomplizieren. Zum Beispiel wenn man in verschiedenen Namensräumen gleiche Namen verwendet.

Die Frage ist hier, ob es vielleicht einen Mittelweg gibt. Quasi eine sichere, eindeutige Variante. Von meinem Standpunkt aus würde ich aber eigentlich gänzlich auf typedefs und Co verzichten. Sinn macht es für mich sowieso nur (in C++) für längliche Templates.
Ohne Input kein Output.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Brainstorming Programmiersprache

Beitrag von dot »

Ich denk bevor man hier beginnen kann zu diskutieren, müsste man erstmal die Grundphilosophie dieser hypothetischen neuen Sprache erklären.

Ohne irgendwelche Design Goals fehlt der Diskussion jegliche Grundlage...

Also: Was genau willst du mit dieser Sprache erreichen?
Florian Keßeler
Beiträge: 75
Registriert: 24.07.2002, 00:00
Wohnort: Bremen
Kontaktdaten:

Re: Brainstorming Programmiersprache

Beitrag von Florian Keßeler »

@dot: Ich verstehe das als den Punkt zur Findung eben dieser Grundphilosophie. Und in diesem Sinne fange ich auch gleich mal an zu philosphieren:

A. Eigentlich bin ich ein großer Freund, rein funktionaler Sprachen wie z.B. Haskell. Aber manche Sachen sind werden durch die Forderung reiner Funktionalität leider auch verkompliziert (eben alles mit Nebenwirkungen wie z.B. I/O). Deshalb wäre hier ein schönes Konzept für eine vielleicht nicht ganz so reine funktionale Sprache nett.

B. Ergibt sich ja schon aus Punkt A... eine hübsche Möglichkeit, beides bequem zu vereinen wäre schön.

C. Ich mag es eigentlich nicht, Konventionen fest vorzugeben, weil sie irgendwem grundsätzlich nicht passen. Aber andererseits hat es Vorteile, wenn man sich nicht bei jedem Projekt in neue obskure Vorgaben einarbeiten muss.

D. Trotz aller Schwierigkeiten, die das mit sich bringt, mag ich Mehrfachvererbung. Wenn man sie mal braucht, freut man sich. Reine Interfaces würde ich am ehesten wie bei C++ über rein abstrakte Klassen machen und kein eigenes Sprachkonzept dafür anbieten, aber das ist vermutlich Geschmackssache. Daten außerhalb von Klassen würde ich persönlich aus verschiedenen Gründen verbieten, freistehende Funktionen allerdings nicht. Ich finde es ziemlich unnatürlich, wie es z.B. bei Java gehandhabt wird. Eine Klasse zu haben, aus der bei Programmstart eine statische Methode aufgerufen wird... dann doch lieber direkt aufrufen, außerdem erlaubt es teilweise mehr Kapselung, freistehende Funktionen zu haben, die nur öffentliche Methoden von Objekten benutzen anstatt Memberfunktionen zu nutzen, die direkt auf die privaten Daten zugreifen könne.

E. Macros und Präprozessor würde ich komplett weglassen. Ein Templatesystem wie in C++ kann fast alles, was man sich zur Compilezeit wünschen kann. Alle Sachen, für die man in C++ zwingend noch den Präprozessor braucht kann man einfach weglassen (Includeguards z.B. in dem man ein "echtes" Modulsystem anbietet, ohne Includedateien)

F. Eine gute Sprachdefinition sollte alles das können. Haskell lässt sich z.B. hervorragend Interpretieren (ghci) oder auch übersetzen (ghc). Nur mit dem Ausführen auf z.B. der Java VM tut Haskell sich schwer, liegt aber so weit ich weiß eher an der Java VM als an der Sprachdefinition. Zwecks Anbindung an bestehende Compilerframeworks würde ich sogar einen Zwischencodegenerator bevorzugen, so bekommt man einige Lowlevel-Optimierungen und Platform-Portierungen umsonst.

G. Ich mag zwar die Freiheiten, die z.B. C++ beim Speichermanagement bietet, aber das passt nicht ganz zu meinen Auffassungen der Punkte A und B. Zeiger z.B. automatisch in Form von shared_ptr zu verpacken wäre eine gute Sache, um sich (und dem Programmierer) nicht mit nem GC das Leben schwer machen zu müssen, der immer im falschen Moment losläuft... Eine Möglichkeit zur Arbeit mit unsicherem Speicher könnte irgendwie noch schön gekapselt daher kommen, eventuell mit dem gleichen Konzept, das auch reine Funktionen von Nebenwirkungen abtrennt.

H. Wenn man weiß, wie viele Probleme Threaderzeugung und Synchronisation bei C++ gemacht haben, bevor es irgendwann plattformübergreifende Bibliotheken dafür gab (z.B. Qt), sollte man sowas direkt in die Sprache einbauen. An der Stelle könnte man auch über sowas wie atomare Blöcke, lockfreie Datenstrukturen und ähnlichem Nachdenken und wiefern sich deren Vorhandensein direkt in der Sprache (statt in einer Bibliothek) vielleicht positiv auswirken könnte.

I. Einrückung als Sprachmittel finde ich bei Haskell und Python eigentlich sehr angenehm. Es spart auch die lästige Frage danach, wo die geschwungenen Klammern hinkommen und zwingt Programmieranfänger dazu, sich über Verschachtelung Gedanken zu machen. Operatorüberladung finde ich, trotz allen Misbrauchs, der damit getrieben wird, sehr gut, weil sie eben auch sehr elegante Arbeitsweisen erlaubt.

J. Streams sind wohl mehr oder weniger der Default für I/O aller Art geworden. Ein einheitliches Interface für alle Arten von I/O ist natürlich schön (wie es z.B. UNIX seit jeher anbietet). Eingebaute Sprachfeatures für asynchrone I/O wären sicher auch nicht zu verachten.

K. Funktionszeiger kann man sich (oder zumindest schöner integrieren) wenn Funktionen first-class Objekte sind.

L. Closures und Lambdas sind eine bequeme und gute Möglichkeit, meine Vorstellung von Punkt K zu erreichen und sie erlauben sehr angenehme, elegante Programmierstile. Sollten also in jeder brauchbaren Sprache vorhanden sein ;-)

M. Hierzu gibt es nicht viel zu sagen. Man sollte vielleicht gucken, ob es für als "rein funktional" markierte Programmabschnitte die Möglichkeit gibt, Schleifen zu verbieten, bzw. ob das weitere Vorteile bringt.

N. Exceptions sollten vorhanden sein, wenn man allerdings throws-Deklarationen einführt, sollten die auch mehr bringen als in C++ und verpflichtend für jede Funktion sein (wer keine hat, darf nix werfen). Assertions und vor allem auch statische (compiletime) Assertions sind eine schöne Sache. Debugging würde ich nicht in die Sprache mit aufnehmen, sondern es nur möglichst leicht machen, bestehende Debugger anzubinden.

O. Hierzu habe ich nicht viel Meinung. Ich finde die C++11-Methode gut.

P. Würde ich in der Standardbibliothek verstecken, allerdings im Sinne der funktionalen Aspekte einen Listentyp als festen Sprachbestandteil (mit angenehmer, kurzer Syntax) anbieten.

Q. const wäre ja schon allein für die Einführung eines pure functional Modus notwendig. Der Einfachheit halber würde ich auch alles als Referenz anlegen, getrackt über Referenzzähler o.ä..

R. Ein echtes Modulkonzept hat eigentlich nur Vorteile gegenüber dem Headerdatei/Namespace-Mischmasch von C++. Außerdem sind zwei getrennte Dateien für Deklaration und Definition irgendwie Banane. Ich würde da also auch eher den Java/Python/fast-alles-außer-C-Weg gehen.

S. Typedef finde ich gut und nützlich, die Doppeldeutigkeit fällt eh spätestens dann auf, wenn ich zwei Funktionen mit der gleichen Syntax global exportiere. Der Linker wird sich bedanken. Ansonsten würde ich nicht erlauben, ganze Namensräume/Module zu importieren, sondern denen nur neue Namen zu geben, also so wie in C++ namespace x = y; Außerdem würde ich auch bei statischer Typisierung und etwas wie C++11 auto bleiben. Dynamische Typisierung zieht einen Rattenschwanz an potenziellen Laufzeitproblemen nach sich.

T. Finde ich gut. Bis auf die Parse-Funktionen. Die gehören da imho nicht rein, sondern als Operator o.ä. an die Streamobjekte gekoppelt, wie es halt auch bei C++ schon ist.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Brainstorming Programmiersprache

Beitrag von BeRsErKeR »

dot hat geschrieben:Ich denk bevor man hier beginnen kann zu diskutieren, müsste man erstmal die Grundphilosophie dieser hypothetischen neuen Sprache erklären.

Ohne irgendwelche Design Goals fehlt der Diskussion jegliche Grundlage...

Also: Was genau willst du mit dieser Sprache erreichen?
Prinzipiell geht es um einen Entwurf für eine allgemeingültige Sprache, die nicht nur für spezielle Zwecke nützlich ist, sondern auch global zum Einsatz kommen kann. Erreichen möchte ich in erster Linie, dass die guten Aspekte vorhandener Sprachen kombiniert werden, eventuell neue Features hinzukommen und Aspekte eliminiert werden, die Nachteile bringen, eventuell Performance einbüßen oder die Lesbarkeit/Wartbarkeit verschlechtern. Das sind aber nur Beispiele. Es geht wie gesagt nicht mal so sehr darum, ob diese Sprache jemals entwickelt wird, sondern um eine Zusammentragung von Ideen, Erfahrungen, Wünschen, usw. In diesem Forum gibt es sehr viele begabte Programmierer, wo also sonst könnte man besser darüber philosophieren und diskutieren?

Florian Keßeler hat geschrieben:C. Ich mag es eigentlich nicht, Konventionen fest vorzugeben, weil sie irgendwem grundsätzlich nicht passen. Aber andererseits hat es Vorteile, wenn man sich nicht bei jedem Projekt in neue obskure Vorgaben einarbeiten muss.
Eben aus dem letztgenannten Grund bin ich eigentlich eher für festere Vorgaben. Man denke nur an so Sachen wie CMyClass, wo selbst heute noch einige Programmierer denken, dass das 'C' am Anfang Pflicht bei Klassen ist. Hätte man eine strikte Regel, wäre es halt recht eindeutig. Wenn sich alle Bezeichner in einer bestimmten Form unterscheiden, würden einige Doppeldeutigkeiten beseitigt werden. Man denke nur an sowas:

Code: Alles auswählen

class apple { };
apple apple; // shit I have to rename it to _apple or something like that
Selbst wenn man Hilfestellungen nimmt bei dem man das bei der Deklaration unterscheiden kann, so kann es im weiteren Verlauf dennoch zu Ungereimtheiten führen. Ist es nun der Klassenname oder ein Objekt? Ganz zu schweigen von Operationen die eventuell auf beidem Arbeiten können und dann vielleicht sogar das falsche angenommen wird.

Und man hat einfach eine einheitlichere Struktur, die das Lesen von Code für jeden Programmierer vereinfacht und vielleicht auch das automatisierte Auswerten von Code und die Arbeit des Compilers/Parsers vereinfacht.
Florian Keßeler hat geschrieben:D. ... Daten außerhalb von Klassen würde ich persönlich aus verschiedenen Gründen verbieten, freistehende Funktionen allerdings nicht. Ich finde es ziemlich unnatürlich, wie es z.B. bei Java gehandhabt wird. Eine Klasse zu haben, aus der bei Programmstart eine statische Methode aufgerufen wird... dann doch lieber direkt aufrufen, außerdem erlaubt es teilweise mehr Kapselung, freistehende Funktionen zu haben, die nur öffentliche Methoden von Objekten benutzen anstatt Memberfunktionen zu nutzen, die direkt auf die privaten Daten zugreifen könne.
Sehe ich genauso. Dieses "Alles-gehört-in-eine-Klasse"-Konzept widerstrebt mir und wie du schon sagtest können globale Funktionen die Kapselung erhöhen. Es ist einfach sinnlos Funktionen in Klassen zu packen, nur damit man alles in Klassen hat. Global kann ja auch namespace-lokal bedeuten, prinzipiell auch mit einem globalen Namespace oder Root-Namespace.

Florian Keßeler hat geschrieben:E. Macros und Präprozessor würde ich komplett weglassen. Ein Templatesystem wie in C++ kann fast alles, was man sich zur Compilezeit wünschen kann. Alle Sachen, für die man in C++ zwingend noch den Präprozessor braucht kann man einfach weglassen (Includeguards z.B. in dem man ein "echtes" Modulsystem anbietet, ohne Includedateien)
Ich bin auch kein Freund vom Präprozessor. Er mag für bestimmte Aufgaben (z.B. Textersetzung) geeignet sein, aber er bringt einfach viel zu viele Nachteile mit sich (keine Debugmöglichkeit, Verschleierung von Abhängigkeiten, usw), als dass er in modernen Sprachen noch Anwendung finden sollte. Ich hab es trotzdem zur Diskussion gestellt. Vielleicht hat ja auch jemand andere Argumente oder kann einen "guten" Präprozessor skizzieren. Templates find ich auch wichtig, aber eventuell sind sie noch verbesserungswürdig (von C++ ausgehend). Es gibt ja auch noch so Sachen wie Concepts usw. Hab da leider zu wenig Erfahrung um was Produktives beizutragen denk ich.

Florian Keßeler hat geschrieben:F. Eine gute Sprachdefinition sollte alles das können. Haskell lässt sich z.B. hervorragend Interpretieren (ghci) oder auch übersetzen (ghc). Nur mit dem Ausführen auf z.B. der Java VM tut Haskell sich schwer, liegt aber so weit ich weiß eher an der Java VM als an der Sprachdefinition. Zwecks Anbindung an bestehende Compilerframeworks würde ich sogar einen Zwischencodegenerator bevorzugen, so bekommt man einige Lowlevel-Optimierungen und Platform-Portierungen umsonst.
Naja ich weiß nicht so recht. Wenn etwas interpretierbar ist, habe ich immer die Befürchtung, dass es dann in kompilierter Binärform nicht so leistungsfähig ist, wie eine rein kompilierbare Sprache. Aber das ist sicher eine Designfrage. Ich will diesen Punkt aber auch deshalb mit als Denkanstoss nutzen, indem man vielleicht auch mal philosophiert, was man beachten muss, wenn beides möglich sein soll und beides ein recht effektives Programm erzeugt.

Florian Keßeler hat geschrieben:H. Wenn man weiß, wie viele Probleme Threaderzeugung und Synchronisation bei C++ gemacht haben, bevor es irgendwann plattformübergreifende Bibliotheken dafür gab (z.B. Qt), sollte man sowas direkt in die Sprache einbauen. An der Stelle könnte man auch über sowas wie atomare Blöcke, lockfreie Datenstrukturen und ähnlichem Nachdenken und wiefern sich deren Vorhandensein direkt in der Sprache (statt in einer Bibliothek) vielleicht positiv auswirken könnte.
Ich hatte mir mal folgendes überlegt. Da ein Thread ja eigentlich immer mit einer Funktion verknüpft ist, könnte man ja einen Thread auch direkt als eine abgewandelte Funktion definieren. Etwa in der Form:

Code: Alles auswählen

thread MyThread(int arg)
{
    ...
}

MyThread my_thread;
my_thread.start();
while (my_thread.running)
    ...;
Sonst hat man immer den Thread als Objekt und die Einsprungsfunktion separat. Ist vielleicht auch eine Philosophiefrage aber ich finds einfach umständlich ein Threadobjekt und noch eine Extrafunktion anzulegen.

Florian Keßeler hat geschrieben:I. Einrückung als Sprachmittel finde ich bei Haskell und Python eigentlich sehr angenehm. Es spart auch die lästige Frage danach, wo die geschwungenen Klammern hinkommen und zwingt Programmieranfänger dazu, sich über Verschachtelung Gedanken zu machen. Operatorüberladung finde ich, trotz allen Misbrauchs, der damit getrieben wird, sehr gut, weil sie eben auch sehr elegante Arbeitsweisen erlaubt.
Ich bin geteilter Meinung. Ich finde es recht gut innerhalb von Blöcken immer eine passende Einrückung vorzuschreiben, aber ganz ohne geschweifte Klammern oder ähnlichem auszukommen, kann schon etwas unübersichtlich werden. Es fehlen die klaren Grenzen, z.B. bei Klassen, Namensräumen usw. Und falls Schleifen-Bodies mal länger werden gilt dort das gleiche. Prinzipiell finde ich aber die Einrückung schon gut. Z.B. ist eine Klasse im Namespace um eins weiter eingerückt und Member der Klasse wiederum eins weiter usw. Auch dies trägt mMn extrem zur Lesbarkeit und Übersicht bei.

Florian Keßeler hat geschrieben:J. Streams sind wohl mehr oder weniger der Default für I/O aller Art geworden. Ein einheitliches Interface für alle Arten von I/O ist natürlich schön (wie es z.B. UNIX seit jeher anbietet). Eingebaute Sprachfeatures für asynchrone I/O wären sicher auch nicht zu verachten.
Mit gefällt eine transparente/flexible/austauschbare Schnittstelle für lokale I/O, Pipes und Netzwerkdaten sehr gut. Wenn ich dran denke, dass ich in C++ direkt per Stream-Operatoren von einem Socket lesen oder schreiben kann, wär das schon ne tolle Sache. Auch in Hinblick auf verteilte Applikationen/Systeme.

Florian Keßeler hat geschrieben:R. Ein echtes Modulkonzept hat eigentlich nur Vorteile gegenüber dem Headerdatei/Namespace-Mischmasch von C++. Außerdem sind zwei getrennte Dateien für Deklaration und Definition irgendwie Banane. Ich würde da also auch eher den Java/Python/fast-alles-außer-C-Weg gehen.
Ich sehe auch nur Vorteile. Allerdings haben da vielleicht andere Leute auch noch andere Meinungen zu. Mal abwarten.

Florian Keßeler hat geschrieben:T. Finde ich gut. Bis auf die Parse-Funktionen. Die gehören da imho nicht rein, sondern als Operator o.ä. an die Streamobjekte gekoppelt, wie es halt auch bei C++ schon ist.
Das waren nur Beispiele. Ich finde solche Dinge aber auch angenehm. Die Form ist ja erstmal egal, aber das sind ja in der Regel sogar statische Daten, die zur Compilezeit bekannt sind. Meine Idee wäre, dass es TypeTraits direkt auf den Typ gibt, aber auch für konkrete Objekte des Typs. Z.B. ein length() auf einen String oder ein dynamisches Array usw. Dabei muss man natürlich erstmal festlegen ob String und Arrays Teil der Sprache sind oder Bestandteil einer Library. Aber man kann ja auch an Dinge wie if (5.typename() == "int") denken und so Sachen. ;)
Ohne Input kein Output.
Florian Keßeler
Beiträge: 75
Registriert: 24.07.2002, 00:00
Wohnort: Bremen
Kontaktdaten:

Re: Brainstorming Programmiersprache

Beitrag von Florian Keßeler »

BeRsErKeR hat geschrieben: Ich hatte mir mal folgendes überlegt. Da ein Thread ja eigentlich immer mit einer Funktion verknüpft ist, könnte man ja einen Thread auch direkt als eine abgewandelte Funktion definieren. Etwa in der Form:

Code: Alles auswählen

thread MyThread(int arg)
{
    ...
}

MyThread my_thread;
my_thread.start();
while (my_thread.running)
    ...;
Finde ich nicht so schön. Dann musst du dich vorher entscheiden, ob deine Funktion vielleicht irgendwann auch mal als Thread ausgeführt werden darf. Und wenn du die falsche Entscheidung triffst, darfst du deinen ganzen Code umschreiben oder doch noch eine eigene Einstiegsfunktion schreiben. Da würde ich doch eher erlauben, anonyme Funktionen als Einstieg zu erlauben (wie es halt eben auch in C++11 oder Python problemlos möglich ist). Dann kannst du notfalls deinen Stil von oben implementieren, oder eben eine bestehende Funktion aufrufen, oder direkt deren Namen benutzen usw.
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: Brainstorming Programmiersprache

Beitrag von antisteo »

Was definitiv rein müsste:

Eine turing-mächtige funktionale Programmiersprache zum Aufbau des imperativen Codes

Sprich: Ein Templatesystem, in das ich auch Code Injection und partielle Klassen definieren kann. Ein funktionales Programm, das mir imperativen Zwischencode ausspuckt.
Mit diesem Templatesystem muss ich also von jeder Kompilationseinheit aus die Möglichkeit haben, globale Seiteneffekte während des Compilevorgangs auszulösen (solange mir das Template das erlaubt)
Im Prinzip will ich jedes Feature in exakt eine Datei stecken und diese Feature-Datei soll ihren Code im Programm verteilen. Mit einem Häkchen in der IDE wird das Feature dann an- und abschaltbar.

Außerdem Wunschliste:
- Closures
- Array und assoziatives Array in Standardbibliothek und mit effizienter Implementierung
- Bitte kein Include
- Irgendein Konzept für Parallelverarbeitung und verteilte Software (nachrichtenbasierte Objekte?)
- Irgendein Konzept, um High-Level-Optimierungspattern zu definieren (Irgendwelche Code-Äquivalenzen a la string a + "" == string a)
- Schnellerer Kompiliervorgang als bei C++
- Kompatibilität mit Linkern, um C-Bibliotheken nutzen zu können
- Ein JIT-Modul für die Nutzung als Scriptsprache
- Ein Sicherheitskonzept, damit selbst DAU-Programmierer keinen Code schreiben können, der einen inkonsistenten Zustand eines Objektes erlaubt
- LLVM benutzen ;)
- Den Compiler in der eigenen Sprache schreiben
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Brainstorming Programmiersprache

Beitrag von BeRsErKeR »

antisteo hat geschrieben:Eine turing-mächtige funktionale Programmiersprache zum Aufbau des imperativen Codes

Sprich: Ein Templatesystem, in das ich auch Code Injection und partielle Klassen definieren kann. Ein funktionales Programm, das mir imperativen Zwischencode ausspuckt.
Mit diesem Templatesystem muss ich also von jeder Kompilationseinheit aus die Möglichkeit haben, globale Seiteneffekte während des Compilevorgangs auszulösen (solange mir das Template das erlaubt)
Im Prinzip will ich jedes Feature in exakt eine Datei stecken und diese Feature-Datei soll ihren Code im Programm verteilen. Mit einem Häkchen in der IDE wird das Feature dann an- und abschaltbar.
Um ehrlich zu sein kann ich dir nicht ganz folgen. Kannst du das noch etwas besser veranschaulichen?

antisteo hat geschrieben: - Kompatibilität mit Linkern, um C-Bibliotheken nutzen zu können
Sowas habe ich mir auch gedacht. Aber die Frage ist wie abhängig man sich dadurch macht bzw. ob man sich dann wieder an irgendeiner Stelle einschränken muss. Man bräuchte ja z.B. eine Art Mapping, falls FunctionCalls in der Sprache komplett anders aufgebaut sind und so Sachen.

antisteo hat geschrieben: - Den Compiler in der eigenen Sprache schreiben
Bräuchte man dann nicht erstmal einen Compiler, der nicht in der Sprache geschrieben ist? :o
Ohne Input kein Output.
Florian Keßeler
Beiträge: 75
Registriert: 24.07.2002, 00:00
Wohnort: Bremen
Kontaktdaten:

Re: Brainstorming Programmiersprache

Beitrag von Florian Keßeler »

Normalerweise hast du einen kleinen Bootstrap-Compiler, der tatsächlich in einer anderen Sprache geschrieben ist (oder z.B. für eine andere Implementierung deiner Sprache), der nur das notwendigste kann, um den tatsächlichen Compiler zu bauen.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Brainstorming Programmiersprache

Beitrag von dot »

Florian Keßeler hat geschrieben:Normalerweise hast du einen kleinen Bootstrap-Compiler, der tatsächlich in einer anderen Sprache geschrieben ist (oder z.B. für eine andere Implementierung deiner Sprache), der nur das notwendigste kann, um den tatsächlichen Compiler zu bauen.
Viel Spaß beim Debuggen ;)
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Brainstorming Programmiersprache

Beitrag von BeRsErKeR »

Florian Keßeler hat geschrieben:
BeRsErKeR hat geschrieben: Ich hatte mir mal folgendes überlegt. Da ein Thread ja eigentlich immer mit einer Funktion verknüpft ist, könnte man ja einen Thread auch direkt als eine abgewandelte Funktion definieren. Etwa in der Form:

Code: Alles auswählen

thread MyThread(int arg)
{
    ...
}

MyThread my_thread;
my_thread.start();
while (my_thread.running)
    ...;
Finde ich nicht so schön. Dann musst du dich vorher entscheiden, ob deine Funktion vielleicht irgendwann auch mal als Thread ausgeführt werden darf. Und wenn du die falsche Entscheidung triffst, darfst du deinen ganzen Code umschreiben oder doch noch eine eigene Einstiegsfunktion schreiben. Da würde ich doch eher erlauben, anonyme Funktionen als Einstieg zu erlauben (wie es halt eben auch in C++11 oder Python problemlos möglich ist). Dann kannst du notfalls deinen Stil von oben implementieren, oder eben eine bestehende Funktion aufrufen, oder direkt deren Namen benutzen usw.
Da hast du natürlich recht. Darum ist es gut andere Meinungen zu hören. Man könnte das Design aber auch etwas abändern, sodass der Wechsel von Thread und Funktion einfach durch das Austauschen des Schlüsselworts "thread" mit "function" realisierbar ist. Dazu müsste man aber die Art des Aufrufs von Funktionen kompatibel zum Starten von Threads machen. Beispielsweise:

Code: Alles auswählen

function MyFunc(...) -> int { }
thread MyThread(...) -> int { }

MyFunc myfunc;
MyThread mythread;

myfunc.exec(arg1, arg2, ...);
mythread.exec(arg1, arg2, ...);
Nur so als Beispiel. Dann hätte man aber wieder den Nachteil, dass Funktionsaufrufe komplexer sind bzw. man sich immer Instanzen von Funktions-Objekten anlegen muss. Vorteil wäre aber, dass man so gleich implizit eine Art Funktionszeiger hat. Man könnte sich also Funktionsobjekte anlegen und andere Funktionen zuweisen. Das könnte sogar in einer Art Polymorphie münden, indem man Methoden nicht überschreibt, sondern den Funktionsobjekten der Klasse etwas anderes zuweist.

Code: Alles auswählen

function MyFunc(x: int) -> int
{
    return int(x + 2);
}

function MyFunc2(x: int) -> int
{
    return int(x + 3);
}

class MyBaseClass
{
    public myfunc : MyFunc;
}

class MyClass -> MyBaseClass
{
    public this()
    {
        myfunc(MyFunc2.new); // oder erneute Typdeklaration auf bestehende Funktion?: myfunc : MyFunc2;
        // wahlweise auch: myfunc(myFunc2.instance);
    }
}

main()
{
    x : MyBaseClass;
    y : MyClass;
    z : int(5);

    result1 : int(x.myfunc.exec(z)); // result1 is 7
    result2 : int(y.myfunc.exec(z)); // result2 is 8
}
Klassen könnten so auch klassenfremde Funktionen als Objekt anlegen und über das Klasseninterface anbieten. Problematisch wäre allerdings, dass man die Schnittstelle von außen ändern kann, indem man Methoden neu zuweist. Aber das könnte man ja nur innerhalb des Klassenkonstruktors erlauben oder ähnliches. Vielleicht auch das public durch was Neues wie interface ersetzen. Solch gekennzeichnete Objekte können dann zwar von außen aufgerufen oder gelesen (für Variablen) werden, aber nur innerhalb des Konstruktors geändert werden. Man kann so das Interface der Klasse im Konstruktor beeinflussen und eventuell mit verschiedenen Konstruktoren, sogar unterschiedliche Interfaces anbieten. Man hätte auch gleich etwas für Readonly-Properties. :D Nachtrag: Ich frage mich allerdings gerade ob das so gut ist. Das Klasseninterface sollte ja vermutlich gleich bleiben. Vielleicht dann eher eine Sektion in der Klasse, wo man das Interface anpassen (vergleichbar mit dem Überladen von Methoden) kann. Wäre aber wahrscheinlich schon wieder viel zu umständlich...

Problematisch wären dann allerdings auch so Sachen wie if (mythread.running), da dies für normale Funktionen bedeutungslos wäre. Wobei man so aus einem anderen Thread auch gucken könnte, ob eine bestimmte Funktion gerade in einem anderen Thread läuft.
Ohne Input kein Output.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Brainstorming Programmiersprache

Beitrag von BeRsErKeR »

Mal eine kleine Spielerei:

Code: Alles auswählen

function MyGlobalFunc(arg : int) -> int
{
    return int(arg + 5);
}

class MyBaseClass
{
    interface calc : MyGlobalFunc;
    interface name : string("MyBaseClass");
    // public ist für Methoden nicht erlaubt, es sei denn man will ermöglichen die Schnittstelle zur Laufzeit zu ändern
    // public für Variablen ist gültig, der Wert ist dann nicht read-only
}

class MyClass -> MyBaseClass
{
    private function MyOwnFunc(arg : int) -> int
    {
        return int(arg + 2);
    }

    interface calc : MyOwnFunc; // Überschreiben
    // name wird von MyBaseClass geerbt (Variablen können nicht überschrieben werden, aber geändert sofern sie nicht konstant sind)
}

main()
{
    x : MyBaseClass;
    y : MyClass;

    result1 : int(x.calc.exec(5)); // result1 is 10
    result2 : int(y.calc.exec(5)); // result2 is 7
    name : string(y.name); // name is "MyBaseClass"
}
public Methoden könnte man eventuell nutzen, wenn man dynamisch die Schnittstelle einer Klasse ändern will. Zum Beispiel für eine Art Signal-Slot-System oder ähnliches.
Ohne Input kein Output.
Florian Keßeler
Beiträge: 75
Registriert: 24.07.2002, 00:00
Wohnort: Bremen
Kontaktdaten:

Re: Brainstorming Programmiersprache

Beitrag von Florian Keßeler »

dot hat geschrieben:
Florian Keßeler hat geschrieben:Normalerweise hast du einen kleinen Bootstrap-Compiler, der tatsächlich in einer anderen Sprache geschrieben ist (oder z.B. für eine andere Implementierung deiner Sprache), der nur das notwendigste kann, um den tatsächlichen Compiler zu bauen.
Viel Spaß beim Debuggen ;)
Ich habe mal einen Artikel gelesen, den ich leider grade nicht finden kann, in dem der Autor gezeigt hat, dass auch Open Source Compiler ein gravierendes Sicherheitsproblem haben: Neuere Version des GCC werden fast ausschließlich mit anderen, binär vertriebenen, älteren GCCs übersetzt. Es wäre möglich, im GCC Schadcode zu verstecken, der beim Übersetzen des GCC diesen Code wieder in den neuen Compiler integriert. Als Ergebnis hätte man dann eine Folge von Compilern, bei denen man nie sicher sein kann, ob sie nicht Schadcode enthalten, weil nur irgendwer in einer ausreichend großen Menge binäre GCC-Kopien mit diesem Schadcode verteilen müsste.

Den Einfluss des ursprünglichen Compilers wird man also niemals mit Sicherheit los (außer man kontrolliert den Assembler-Output des Compilers). Aber so ist es eben mit allem. Du wirst immer das Problem haben, festzustellen, ob dein eigener Code fehlerhaft ist, oder doch der Compiler oder gar dessen Bootstrap-Compiler.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Brainstorming Programmiersprache

Beitrag von dot »

Ich meinte damit eher: Für diese potentielle neue Programmiersprache existieren anfangs absolut keine Tools etc. Imo wird Bootstrapping erst sinnvoll, wenn ich für meine neue Sprache eine IDE mit Debugger hab. Wieso sollte ich mir die Arbeit machen, den Compiler in eine Sprache zu übersetzen, für die noch keine Tools existieren?

Rein prinzipiell ist es natürlich toll wenn die Sprache self-hosting ist. Aber imo ist das für den Anfang eher sehr nebensächlich...
Alexander Kornrumpf
Moderator
Beiträge: 2119
Registriert: 25.02.2009, 13:37

Re: Brainstorming Programmiersprache

Beitrag von Alexander Kornrumpf »

Der Artikel war es wahrscheinlich:

http://cm.bell-labs.com/who/ken/trust.html
Florian Keßeler
Beiträge: 75
Registriert: 24.07.2002, 00:00
Wohnort: Bremen
Kontaktdaten:

Re: Brainstorming Programmiersprache

Beitrag von Florian Keßeler »

Ich finde sogar, dass das heutzutage einfach insgesamt unsinnig ist. Ich wollte nur anmerken, wie es "eigentlich" gemacht wird, im Sinne von "was man halt in der Vorlesung Compilerbau gesagt bekommt" ;-)

@Alexander, nee, das war ein neuerer Artikel. Ich muss noch mal auf die Suche gehen.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Brainstorming Programmiersprache

Beitrag von BeRsErKeR »

Hat sonst niemand noch ein Paar Ideen, Vorschläge oder Anmerkungen zu dem bereits Gesagten? Ich hatte ein wenig mehr Feedback erwartet. Bislang kam ja noch nicht so viel dabei raus.
Ohne Input kein Output.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Brainstorming Programmiersprache

Beitrag von CodingCat »

BeRsErKeR hat geschrieben:Hat sonst niemand noch ein Paar Ideen, Vorschläge oder Anmerkungen zu dem bereits Gesagten? Ich hatte ein wenig mehr Feedback erwartet. Bislang kam ja noch nicht so viel dabei raus.
Nunja, zum einen ist ZFX nicht so sonderlich belebt, zum anderen ist es bisher etwas schwierig, Feedback abzugeben. Wie dot schon zu Anfang des Threads sagte, bedarf es für sinnvolles Feedback erstmal einiger Grundideen, die die Sprache in ihren Grundzügen bestimmen. Klar willst du in irgendeiner Form die guten Aspekte bisheriger Sprachen kombinieren, aber hierzu musst du diese eben erstmal identifizieren. Solange du diese nicht gesammelt hast, und ggf. einzelne Punkte mit klarer Zielvorstellung ansprichst, bleibt uns nicht viel anderes, als selbst ein solches Best Of zusammenzutragen. Das kostet nicht nur sehr viel Zeit, sondern ist auch relativ witzlos, weil hier die Urquellen in Form von bestehenden Sprachreferenzen und Artikeln der jeweiligen Sprachentwickler/Sprachcommunity wesentlich erkenntnisbringender sind, als es unsere knappen Zusammenfassungen wären.

Zu Threads: Ich glaube kaum, dass ein festes Einbauen von Threads in die Sprache Vorteile bringt. Vermutlich gibt es das in der ein oder anderen Sprachen da draußen, mir fällt aber gerade keine ein. Die Frage ist: Warum sollten Threads in die Sprache eingebaut werden? Schlussendlich muss das Threading sowieso über irgendeiner plattformabhängige API laufen. Da jede Sprache ohnehin an irgendeiner Stelle die Interoperabilität mit bestehenden Bibliotheken der jeweiligen Plattform anbieten muss, damit überhaupt irgendetwas sinnvolles (abseits festgesetzter Problemfelder) damit konstruiert werden kann, ist die naheliegendste Umsetzung doch wohl die Bereitstellung von Threads durch Bibliotheksfunktionalität. Solange es keinen guten Grund dafür gibt, erhöht jedes fest in die Sprache eingebaute Feature nur unnötig die Komplexität der Sprache.
Ein sehr nützliches Feature, das mit Sicherheit nicht nur Threading zu Gute kommt, wären dagegen Closures oder ähnliche Konstrukte, die das Übergeben von Funktionen samt gebundener Parameter ermöglichen. Damit kann eine Threading-Bibliothek das Starten von Threads genau so einfach machen, wie du es in deinen Codeschnipseln bereits angedeutet hast.

Zu den Codeskizzen: Willst du ernsthaft für jeden Funktionsaufruf exec aufrufen? Das zu einem einfachen Funktionsaufruf zu vereinfachen, wäre jetzt wiederum ein Sprachfeature, das sich wohl auf jeden Fall lohnt. ;)
Der Interface-Mechanismus ist mir absolut unklar. Inwiefern unterscheiden sich interface-Attribute von normalen Funktionsobjekt-Attributen? Nebenbei: Das, was du hier baust, sieht aus wie einfacher Polymorphismus durch Funktionszeiger. Funktionszeiger pro Objekt können aber signifikanten Overhead bedeuten. Soll das interface-Keyword diese ein eine V-Tabelle schieben?

Hier wird ein weiteres Problem deutlich: Für sinnvolles Feedback muss klar sein, was genau du eigentlich tun willst und warum du das so tun willst. ;)
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Brainstorming Programmiersprache

Beitrag von BeRsErKeR »

CodingCat hat geschrieben:
BeRsErKeR hat geschrieben:Hat sonst niemand noch ein Paar Ideen, Vorschläge oder Anmerkungen zu dem bereits Gesagten? Ich hatte ein wenig mehr Feedback erwartet. Bislang kam ja noch nicht so viel dabei raus.
Nunja, zum einen ist ZFX nicht so sonderlich belebt, zum anderen ist es bisher etwas schwierig, Feedback abzugeben. Wie dot schon zu Anfang des Threads sagte, bedarf es für sinnvolles Feedback erstmal einiger Grundideen, die die Sprache in ihren Grundzügen bestimmen. Klar willst du in irgendeiner Form die guten Aspekte bisheriger Sprachen kombinieren, aber hierzu musst du diese eben erstmal identifizieren. Solange du diese nicht gesammelt hast, und ggf. einzelne Punkte mit klarer Zielvorstellung ansprichst, bleibt uns nicht viel anderes, als selbst ein solches Best Of zusammenzutragen. Das kostet nicht nur sehr viel Zeit, sondern ist auch relativ witzlos, weil hier die Urquellen in Form von bestehenden Sprachreferenzen und Artikeln der jeweiligen Sprachentwickler/Sprachcommunity wesentlich erkenntnisbringender sind, als es unsere knappen Zusammenfassungen wären.
Da hast du schon Recht. Allerdings können ja alle mal ein paar Features/Aspekte nennen, die sie selbst als sinnvoll oder gelungen empfinden. Ich bin selbst noch dabei einige Aspekte zu identifizieren bzw. zu überlegen wie man diese besser umsetzen kann.

CodingCat hat geschrieben:Zu Threads: Ich glaube kaum, dass ein festes Einbauen von Threads in die Sprache Vorteile bringt. Vermutlich gibt es das in der ein oder anderen Sprachen da draußen, mir fällt aber gerade keine ein. Die Frage ist: Warum sollten Threads in die Sprache eingebaut werden? Schlussendlich muss das Threading sowieso über irgendeiner plattformabhängige API laufen. Da jede Sprache ohnehin an irgendeiner Stelle die Interoperabilität mit bestehenden Bibliotheken der jeweiligen Plattform anbieten muss, damit überhaupt irgendetwas sinnvolles (abseits festgesetzter Problemfelder) damit konstruiert werden kann, ist die naheliegendste Umsetzung doch wohl die Bereitstellung von Threads durch Bibliotheksfunktionalität. Solange es keinen guten Grund dafür gibt, erhöht jedes fest in die Sprache eingebaute Feature nur unnötig die Komplexität der Sprache.
Ein sehr nützliches Feature, das mit Sicherheit nicht nur Threading zu Gute kommt, wären dagegen Closures oder ähnliche Konstrukte, die das Übergeben von Funktionen samt gebundener Parameter ermöglichen. Damit kann eine Threading-Bibliothek das Starten von Threads genau so einfach machen, wie du es in deinen Codeschnipseln bereits angedeutet hast.
Es geht ja nicht unbedingt um die komplette Integration der Funktionalität, die hinter Threads steckt, sondern um ein geeignetes Sprachmittel um Sie in der Sprache leichter benutzbar zu machen. Natürlich hast du grundlegend Recht, aber dazu ist ja gerade dieser Thread hier gedacht. Um mal Ideen zu diskutieren. Dein Beitrag war für mich nun schonmal aufschlussreich. Und das ist ja genau das, was ich erreichen möchte. ;)

CodingCat hat geschrieben:Zu den Codeskizzen: Willst du ernsthaft für jeden Funktionsaufruf exec aufrufen? Das zu einem einfachen Funktionsaufruf zu vereinfachen, wäre jetzt wiederum ein Sprachfeature, das sich wohl auf jeden Fall lohnt. ;)
Der Interface-Mechanismus ist mir absolut unklar. Inwiefern unterscheiden sich interface-Attribute von normalen Funktionsobjekt-Attributen? Nebenbei: Das, was du hier baust, sieht aus wie einfacher Polymorphismus durch Funktionszeiger. Funktionszeiger pro Objekt können aber signifikanten Overhead bedeuten. Soll das interface-Keyword diese ein eine V-Tabelle schieben?

Hier wird ein weiteres Problem deutlich: Für sinnvolles Feedback muss klar sein, was genau du eigentlich tun willst und warum du das so tun willst. ;)
Es waren zunächst erstmal Gedankenspiele. Das exec ist aus der Idee mit den Threads entstanden um syntaktisch weniger Aufwand beim Wechsel von Thread auf normale Funktion und umgekehrt zu haben. Prinzipiell wäre dieser Ansatz ähnlich wie ein Functor-Objekt, dass zusätzlich zu einem ()-Operator noch die exec-Funktion besitzt und somit eher dem Ansatz eines echten (Funktions-)Objekts entspricht. Ich weiß nicht ob es wirklich so schlecht ist das ".exec" zu erzwingen. Wer sagt denn, dass man immer das altbekannte Format eines Funktionsaufrufs nutzen muss. Das exec macht deutlicher was man eigentlich tut.

Das interface-Schlüsselwort kann anstelle von public, private usw. verwendet werden und ist nicht nur auf Funktionsobjekte beschränkt, sondern kann in allen Klassen verwendet werden. Es ist wie gesagt erstmal ein grobes Konzept, daher auch "Ein paar Spielereien". Für mich ist das Teil von einem Brainstorming. Mit dem interface-Schlüsselwort gekennzeichnete Methoden, sind ähnlich wie öffentliche virtuelle Methoden, aber halt mit einem etwas anderen Mechanismus. Sie werden nicht direkt in abgeleiteten Klassen überladen, sondern das Objekt weist diesen Methoden oder besser Methodenzeigern im Konstruktor eine schnittstellen-kompatible Funktion zu (die sogar außerhalb der Klasse liegen kann, sofern möglich). Die Polymorphie wird also bei der Konstruktion vorgenommen und kann theoretisch je nach Konstruktor sogar unterschiedlich sein (bei letzterem bin ich mir nicht sicher ob das wirklich so gut ist). Nach außen sind diese Methoden zwar sichtbar und aufrufbar, man kann aber außerhalb des Klassenkonstruktors diesen Methodenzeigern keine neue Funktion zuweisen. Methodenzeiger, die als public und nicht als interface gekennzeichnet sind erlauben auch eine Neuzuweisung von außen und sollten in den meisten Fällen vermieden werden, könnten aber auch ihren Sinn haben. interface-Methoden repräsentieren quasi das Funktionsinterface einer Klasse, welches die Klasse bei der Konstruktion bestimmen kann. Es würde dann virtuelle Methoden ablösen und bräuchte theoretisch keine V-Table, sprich V-Tables wären eventuell komplett überflüssig, da Methoden nur Memberobjekte sind. Das ganze ist natürlich noch nicht ausgereift.

Noch ein Nachtrag: Es drängt sich eventuell die Frage auf, warum man dann nicht gleich private nimmt. Mit interface hat man die Einschränkung, dass Änderungen nur während der Konstruktion (also im Konstruktor) möglich sind. Mit private wäre dies z.B. auch in anderen Methoden möglich. Theoretisch wäre das interface-Schlüsselwort also auch für öffentliche konstante Werte geeignet, die im Konstruktor initialisiert werden (Stichwort: Readonly-Properties).
Ohne Input kein Output.
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: Brainstorming Programmiersprache

Beitrag von antisteo »

BeRsErKeR hat geschrieben:
antisteo hat geschrieben:Eine turing-mächtige funktionale Programmiersprache zum Aufbau des imperativen Codes

Sprich: Ein Templatesystem, in das ich auch Code Injection und partielle Klassen definieren kann. Ein funktionales Programm, das mir imperativen Zwischencode ausspuckt.
Mit diesem Templatesystem muss ich also von jeder Kompilationseinheit aus die Möglichkeit haben, globale Seiteneffekte während des Compilevorgangs auszulösen (solange mir das Template das erlaubt)
Im Prinzip will ich jedes Feature in exakt eine Datei stecken und diese Feature-Datei soll ihren Code im Programm verteilen. Mit einem Häkchen in der IDE wird das Feature dann an- und abschaltbar.
Um ehrlich zu sein kann ich dir nicht ganz folgen. Kannst du das noch etwas besser veranschaulichen?
Beispiel Commandline-Option: Das Projekt besteht aus verschiedenen Features. Jedes Feature führt ein paar neue Commandline-Optionen hinzu. Beispielsweise fügt das Feature "Proxy" einen Parameter "--socks" ein. Mein Commandline-Parser muss jetzt so implementiert werden, dass er von sämtlichen Features die möglichen Optionen einsammelt und mit Funktionen besetzt und die "--help"-Option mit Leben füllt. Außerdem wäre ein Compile-Modus "Dokumentation/man" ganz nett. Das müsste aber kein Compiler- sondern ein Sprachfeature sein.
Weiter mit dem Proxy, der Proxy müsste im Prinzip eine Funktion vor die send-Methode schalten. Das klingt erst mal nach Raketentechnik und wundersamem Meta-Programming, ist aber ganz einfach realisierbar auf Methodenebene. Auf Codeebene löst man das Problem, indem man Stellen im Code benennen kann, an die "Erweiterungsfeatures" dann ihren Code injizieren können.

gwscript erlaubt das in Form eines "foreach", welches zur Compilezeit über einen Pool von Deklarationen läuft. Man kann diese Deklarationen mit einer Eigenschaft taggen (Beispiel: 'Dieses Feature stellt neue Kommandooptionen bereit' oder 'Dieses Feature beantragt einen Eintrag im Menü "Datei"' oder 'Dieses Feature ist ein weiterer nutzbarer Video-Codec'). Diese foreach-Schleife kann man dann über eine benannte Eigenschaft laufen lassen und jede Compile-Iteration lässt sich zusätzlich beeinflussen, indem du ein try{} zur Compilezeit hast: Der Codeblock wird nur in die ausführbare Datei aufgenommen, wenn er sich fehlerfrei kompilieren lässt. Ansonsten keine Meldung. Die Folge war, dass du zusätzlich zur Compilezeit testen konntest, ob die vom Benutzer getaggten Deklarationen wirklich deinen Schnittstellen entsprochen haben.
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4263
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: Brainstorming Programmiersprache

Beitrag von Chromanoid »

Hört sich irgendwie nach aspektorientierter Programmierung an, hehe hast du etwa auf dem wikipedia Artikel dazu gwX-Script untergabracht? :D
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: Brainstorming Programmiersprache

Beitrag von antisteo »

Chromanoid hat geschrieben:Hört sich irgendwie nach aspektorientierter Programmierung an, hehe hast du etwa auf dem wikipedia Artikel dazu gwX-Script untergabracht? :D
Naja irgendwie muss man doch die einfachste vollständige Lösung publik machen.
(Wobei mein Softwarelehrstuhl hatte ein paar Probleme mit dem "einfach")
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4263
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: Brainstorming Programmiersprache

Beitrag von Chromanoid »

Hehe, dann aber bitte mit Verlinkung :) naja der Abschnitt ist sowieso etwas fragwürdig. Mir fehlt da irgendwie eine Erwähnung von http://aopalliance.sourceforge.net/ sowie Java Interceptors + Dependency Injection... Sorry für das OT.

Ich finde Aspekt orientierte Programmierung ziemlich nett. Kann aber auch ziemlich schwer nachzuvollziehende Auswirkungen haben...
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Brainstorming Programmiersprache

Beitrag von CodingCat »

antisteo hat geschrieben:Beispiel Commandline-Option: Das Projekt besteht aus verschiedenen Features. Jedes Feature führt ein paar neue Commandline-Optionen hinzu. Beispielsweise fügt das Feature "Proxy" einen Parameter "--socks" ein. Mein Commandline-Parser muss jetzt so implementiert werden, dass er von sämtlichen Features die möglichen Optionen einsammelt und mit Funktionen besetzt und die "--help"-Option mit Leben füllt. Außerdem wäre ein Compile-Modus "Dokumentation/man" ganz nett. Das müsste aber kein Compiler- sondern ein Sprachfeature sein.
Weiter mit dem Proxy, der Proxy müsste im Prinzip eine Funktion vor die send-Methode schalten. Das klingt erst mal nach Raketentechnik und wundersamem Meta-Programming, ist aber ganz einfach realisierbar auf Methodenebene. Auf Codeebene löst man das Problem, indem man Stellen im Code benennen kann, an die "Erweiterungsfeatures" dann ihren Code injizieren können.

gwscript erlaubt das in Form eines "foreach", welches zur Compilezeit über einen Pool von Deklarationen läuft. Man kann diese Deklarationen mit einer Eigenschaft taggen (Beispiel: 'Dieses Feature stellt neue Kommandooptionen bereit' oder 'Dieses Feature beantragt einen Eintrag im Menü "Datei"' oder 'Dieses Feature ist ein weiterer nutzbarer Video-Codec'). Diese foreach-Schleife kann man dann über eine benannte Eigenschaft laufen lassen und jede Compile-Iteration lässt sich zusätzlich beeinflussen, indem du ein try{} zur Compilezeit hast: Der Codeblock wird nur in die ausführbare Datei aufgenommen, wenn er sich fehlerfrei kompilieren lässt. Ansonsten keine Meldung. Die Folge war, dass du zusätzlich zur Compilezeit testen konntest, ob die vom Benutzer getaggten Deklarationen wirklich deinen Schnittstellen entsprochen haben.
Gibt es irgendeinen Grund, warum sowas zur Compile-Zeit möglich sein muss? Mir fallen gerade keine Anwendungsfälle ein, in denen ein solcher Mechanismus sinnvoll und zugleich Performance-kritisch sein könnte. In C++ geht das btw. zur Laufzeit vollkommen ohne Spracherweiterungen und ganz natürlich. Ein weiteres Beispiel für die Genialität einfacher, aber gut durchdachter Mechanismen in der Sprache. Auf jeden Fall keine Raketentechnik. ;)

Noch was: Wann ist es sinnvoll, fehlerhafte Codeblöcke einfach ohne Fehlermeldung zu ignorieren? Kommt mir spontan sehr fragwürdig vor.

Zu aspektorientierter Programmierung: Bis jetzt habe ich immer nur vollkommen sinnfreie Beispiele gesehen, hat das irgendeinen tatsächlichen Nutzen? (Und wo finde ich gwX-Script auf Wikipedia?)
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4263
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: Brainstorming Programmiersprache

Beitrag von Chromanoid »

Zu aspektorientierter Programmierung:
Also ich habs bis jetzt nur benutzt um Funktionen mit verschiedenen einfachen Aspekten auszustatten und das fand ich ziemlich nett. Man konnte eine Methode mit @Async markieren (und das Ergebnis in eine Future packen) um die Methodeaufrufe automatisch asynchron ablaufen zu lassen. Für Debugging und Performance-Messung kann es auch ziemlich nett sein, da man einfach alle Methoden mit Aufruf-Logging- oder Zeitmess-Aspekten versieht. Sicherheitschecks, die per Aspekt in Methoden eingebunden werden, sind auch ein netter Anwendungsfall. Im Grunde alles was eher administrativen oder rein technischen Charakter hat, kann man so häufig aus der fachlichen Logik einer Anwendung raushalten.

@gwx auf wikipedia :) antiseo hat seine Scriptsprache im wikipedia artikel Aspektorientierte Programmierung reingemogelt :D: http://de.wikipedia.org/wiki/Aspektorie ... rammierung
(der Abschnitt ist eigentlich mehr als fragwürdig :))
Entwicklungsstand der aspektorientierten Programmierung
Die aspektorientierte Programmierung steckt heute noch in den Kinderschuhen. AspectJ z. B. stellt keine vollständig aspektorientierte Lösung dar, weil die Aspektorientierung sich nur auf Klassen beschränkt, die von AspectJ compiliert werden, nicht jedoch für Klassen gilt, die lediglich verwendet werden. Das besonders interessante Einsatzgebiet der Überwachung von Collections ist damit nur sehr eingeschränkt möglich.

Ein anderes Konzept verfolgt die inzwischen eingesetzte Scriptsprache gwX-Script, bei der nur bewusst vom Framework deklarierte Concerns mehrfach von "Packs" (meistens Erweiterungen) ausgefüllt werden können. Damit lässt sich ein nativer Plugin-Ersatz schaffen, der ein Patchen des Hauptprogramms für ein neues Feature unnötig macht.

Außerdem ist strittig, ob und wie aspektorientierte Programmierung auf Objekt-Ebene zu realisieren ist. Schnell, aber enorm speicherintensiv sind Patchlisten für jedes einzelne Objekt. Eine Lösung könnte die Einführung einer Methodeneigenschaft „controllable“ oder „aspect“ sein, welche als Join-Point verwendbare Methoden kennzeichnet, vergleichbar mit „virtual“ in C++, das polymorphe Methoden kennzeichnet. Jedoch zeigen einerseits moderne OO-Sprachen wie Java auf Objektebene ausschließlich virtuelle Methoden, was ein Indikator dafür ist, eine solche Einschränkung nicht einzuführen, andererseits ist eine derartige Einschränkung wider die Natur der aspektorientierten Programmierung. Andere Ansätze, wie AspectJ, beschränken sich auf die Aspektorientierung auf Klassenebene, die gezielte Überwachung bestimmter einzelner Objekte ist nicht deklarativ möglich.

Bis sich die aspektorientierte Programmierung zu einem dominierenden Programmierparadigma wie heute die objektorientierte Programmierung entwickelt hat, dürften noch einige Jahre und Programmiersprachen ins Land gehen. AspectJ ist dabei mit den ersten OO-Schritten in C vergleichbar, aus denen später Objective C und C++ hervorgegangen sind. Man kann davon ausgehen, dass sich auf der Basis der objektorientierten Programmiersprachen Java und C# aspektorientierte Programmiersprachen entwickeln werden, wie einst Oberon und C++ aus Pascal und C entstanden sind. Diese werden den Programmierern ermöglichen, die Aspektorientierung zu erkunden, aspektorientierte Programmiermuster zu entwerfen und schließlich zur Entwicklung ausgereifter aspektorientierter Sprachen und Laufzeitumgebungen führen, wie heute Java oder C# für die Objektorientierung.

Ebenso kann es zu einem Versiegen von Neuentwicklungen im AOP-Bereich kommen, wenn die höhere Abstraktion in der Praxis nicht von einem ausreichenden Anteil von Entwicklern verstanden und eingesetzt wird. Aktuell werden bereits OO-Techniken häufig nicht im Sinne der ursprünglichen Konzeption, sondern ausschließlich zur Erfüllung von Vorgaben eingesetzt. Vor diesem Hintergrund ist das Potential für noch weiter abstrahierende Techniken ungewiss.
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: Brainstorming Programmiersprache

Beitrag von antisteo »

CodingCat hat geschrieben:Zu aspektorientierter Programmierung: Bis jetzt habe ich immer nur vollkommen sinnfreie Beispiele gesehen, hat das irgendeinen tatsächlichen Nutzen? (Und wo finde ich gwX-Script auf Wikipedia?)
Ein Beispiel kann ich dir nennen: Computerspiele und Erweiterungen.
In gwX (http://goldenwipf.de) werden die Aspekte (Template genannt) dazu genutzt, damit Erweiterungen den Spielinhalt an den tiefgreifendsten Stellen umwälzen können, ohne den (durch Prüfsummen geschützten) Hauptcode des Spiels anfassen zu müssen.
Eine genaue Beschreibung der Funktionsweise ist im gwX-Wiki vorhanden: http://goldenwipf.de/wiki/index.php/Gwscript unter Abschnitt Templates
gwScript erlaubt eine Art Templates folgender Art:
Man kann gewissen Bezeichnern (Klassennamen, Funktionsnamen, Variablennamen) einen Tag zuordnen. Jeder Tag hat sozusagen mehrere Bezeichner, die ihm zugeordnet sind. Man weist einen Tag folgendermaßen zu:

Code: Alles auswählen

template Bezeichner: Tag
Mithilfe dieser Metainformationen über Klassen oder globale Variablen kann der Scripter jetzt automatischen Code generieren. So werden zum Beispiel die Packs über dieses System am Anfang des Spiels automatisch geladen. Dieser Aufruf "für jedes Pack" realisiert man durch den »applytemplate«-Abschnitt. Dies ist ein Block ähnlich des if-Blocks, in dem jedes Vorkommen des Bezeichners »template« in Strings, Variablen- und Funktionsnamen etc. durch jeden Bezeichner, dem der angegebene Tag zugeordnet ist, ersetzt wird.

Beispiel:

Code: Alles auswählen

applytemplate(Pack){template.init}
Dieses Beispiel ruft für jedes Pack die init-Methode auf. Wäre z.B. definiert:

Code: Alles auswählen

template Objects: Pack
template Western: Pack
So würde der »applytemplate«-Block folgenden Code erzeugen:

Code: Alles auswählen

Objects.init
Western.ini
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Brainstorming Programmiersprache

Beitrag von BeRsErKeR »

Also ist ein Aspekt bzw. Template eine Art Gruppe/Gruppierung, für die ich bestimmte generelle Aktionen durchführen kann?
Ohne Input kein Output.
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: Brainstorming Programmiersprache

Beitrag von antisteo »

BeRsErKeR hat geschrieben:Also ist ein Aspekt bzw. Template eine Art Gruppe/Gruppierung, für die ich bestimmte generelle Aktionen durchführen kann?
Genau.

Ein weiteres Beispiel findest du in der Betriebssystemwelt: Die Systemdienste von Linux und Grub.
Beide haben einen speziellen Ordner /etc/grub.d bzw. /etc/init.d, welche die Aspekte (Skripte) enthalten. Die Dateinamen folgen einer Konvention, sodass durch das Sortieren eine Reihenfolge der zu startenden Systemdienste oder der aufzulistenden Bootloader-Einträge (Grub) erhält.
Der Vorteil an dem System ist, dass jeder Aspekt in einer extra-Datei steckt und man somit ein Paket installieren kann, welches einfach in den entsprechenden Ordner sein Skript dazusteckt. Die Skripte werden einfach in ihrer Sortierreihenfolge aufgerufen und fügen bei Grub neue Zeilen in die Einstellungsdatei hinzu bzw. starten Systemdienste. Die Aspekte sind auch an- und abschaltbar und weiterer Schnickschnack.

Was aber auch noch wesentlich zum aspektorientierten Programmierstil in gwscript beiträgt, sind die offenen Klassendeklarationen. Ich kann einer Klasse von jeder Datei aus neue Felder und Methoden anhängen. Damit kann ich in Erweiterungspacks das Interface z.B. eines Szenarios erweitern, ohne auf fiese Java-Tricks (aka Designpattern) wie Dekoratoren, Abstract Factories und solchen Schmarrn zurückgreifen zu müssen. Ein kluger Mann sagte einst:
kluger Mann hat geschrieben:Die Anzahl an Designpattern einer Sprache verdeutlicht, wie schlecht sie ist.
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Brainstorming Programmiersprache

Beitrag von CodingCat »

antisteo hat geschrieben:
CodingCat hat geschrieben:Zu aspektorientierter Programmierung: Bis jetzt habe ich immer nur vollkommen sinnfreie Beispiele gesehen, hat das irgendeinen tatsächlichen Nutzen? (Und wo finde ich gwX-Script auf Wikipedia?)
Ein Beispiel kann ich dir nennen: Computerspiele und Erweiterungen.
In gwX (http://goldenwipf.de) werden die Aspekte (Template genannt) dazu genutzt, damit Erweiterungen den Spielinhalt an den tiefgreifendsten Stellen umwälzen können, ohne den (durch Prüfsummen geschützten) Hauptcode des Spiels anfassen zu müssen.
[...]
Beispiel:

Code: Alles auswählen

applytemplate(Pack){template.init}
Dieses Beispiel ruft für jedes Pack die init-Methode auf. Wäre z.B. definiert:

Code: Alles auswählen

template Objects: Pack
template Western: Pack
So würde der »applytemplate«-Block folgenden Code erzeugen:

Code: Alles auswählen

Objects.init
Western.ini
Naja, das fällt für mich nicht wirklich unter aspektorientierte Programmierung, das ist schlussendlich nichts weiter als ein Interface-Methoden-Aufruf über eine Liste zentral gesammelter Objekte. Das lässt sich wie gesagt schon in C++ absolut natürlich formulieren, nutze ich selbst an wenigen Stellen, ist aber doch nicht mehr als ein primitives Plugin-System.
antisteo hat geschrieben:Was aber auch noch wesentlich zum aspektorientierten Programmierstil in gwscript beiträgt, sind die offenen Klassendeklarationen. Ich kann einer Klasse von jeder Datei aus neue Felder und Methoden anhängen. Damit kann ich in Erweiterungspacks das Interface z.B. eines Szenarios erweitern, ohne auf fiese Java-Tricks (aka Designpattern) wie Dekoratoren, Abstract Factories und solchen Schmarrn zurückgreifen zu müssen.
Genau hier sehe ich ein Problem von aspektorientierter Programmierung, dass an Stelle einer sinnvollen Systemaufteilung einfach wahllos Code gestreut wird, der am Ende doch nur in einer einzigen großen und strukturlosen Klasse endet, die letztlich nicht viel mehr ist, als ein unnötiger Container um massig globalen Zustand und globale Funktionen mit Nebenwirkungen.
Design Patterns allgemein als fiese Java Tricks zu bezeichnen, ist offenkundig blödsinnig; ich bin zwar kein pedantischer Verfechter fester Entwurfsmuster, aber schlussendlich ergeben sich diese Muster in jeder Sprache intuitiv bei der Problemlösung, solche Muster wirst du wahrscheinlich sogar in deinen gwX-Scripts finden (sofern diese überhaupt Struktur haben :P).

Noch immer leuchtet mir in Bezug auf aspektorientierte Programmierung jedoch nicht ein, wieso ich allgemein Code in die Methoden unzähliger Klassen streuen sollte. Instrumentierung und Tracing mal beiseite, wo soll das nützlich sein? Code, der automatisch in jede Methode gestreut werden muss, gehört doch ziemlich sicher überhaupt nicht dorthin, sondern entweder eine Ebene höher oder tiefer?!
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4263
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: Brainstorming Programmiersprache

Beitrag von Chromanoid »

Naja, ich würde sagen, man kann komponentenbasierte Systeme, wie sie momentan in der Spielentwicklung populär sind, schon fast als aspektorientierte Programmierung verstehen.

AOP ist vor allem für große Systeme interessant in denen man mit zig zu integrierenden Fremdsystemen zu kämpfen hat. Genau dann ist AOP für das gut, was du da zur Seite stellst. Ich würde behaupten, dass sehr viele Anwendungen im wirtschaftlichen Umfeld genau das brauchen, um effizient fachliche Logik implementieren zu können. AOP ist im Grunde das "Design-Pattern" für die Lösung von:
* Sicherstellung von Zugriffsrechten
* Herstellung von Transaktionssicherheit
* konfigurierbarem detaillierten Logging
* konfigurierbarem Profiling
* Sicherstellung von QoS-Parametern und Service Contracts
Antworten