Hallo Whouzuo,
freut mich, dass Du geantwortet hast. Ein bisschen schade finde ich aber, dass Du eigentlich nicht mehr auf die eigentliche Ausgangsfrage (Matthias Frage im Zusammenhang mit dem, was ich geschrieben habe) eingegangen bist. Vielleicht holst Du das ja noch nach. Wäre doch schön, wenn wir mit Matthias zusammen eine schöne Lösung finden würden.
Aber auch so hat mich interessiert, was zu antwortest. Deshalb hab ich Dich auch zitiert, weil ich Deine Aufgabenstellung gut fand. Ich hatte zuerst auch überlegt, ob ich Dich überhaupt zitieren sollte oder ob das am Ende blöd rüberkommt. Auch wenn ich nicht glaube, dass Du das so aufgefasst hast, hier nochmal explizit: Ich wollte nichts gegen Dich schreiben sondern etwas im Sinne Deiner Aufgabenstellung.
Noch etwas zum Code: Wie ich zuvor schon erwähnt hatte, ging es mir keineswegs um ein konkretes oder vollständiges Beispiel, sondern nur um die Veranschaulichung meiner Idee. Und das im Sinne eines Lehrbeispiels, nicht in dem Sinne, wie man es in der Praxis wahrscheinlich umsetzen würde.
In den Bereich begeben wir uns aber im Folgenden wieder. Nicht schlimm, ist auch interessant. Mich würde aber wie gesagt freuen, wenn wir in einem anderen Zweig des Threads wieder auf Matthias Frage eingehen.
Guter Versuch, aber du hast erstens die Anforderungen verändert
Ja, das habe ich. Und ganz so toll fand ich das auch nicht. Habe deswegen auch nochmal explizit nach Kritik gefragt. Warum ich die Anforderung verändert habe? Eigentlich einfach, ich kann mir einfach nicht vorstellen, wie Du bei Multiple Dispatch nur an einer Stelle Änderungen im Code vornehmen willst, um eine neue Klasse einzufügen (ich bin übrigens weder Informatiker noch sonst etwas in der Richtung und bei Multiple Dispatch weiß ich nur grob, um was es dabei geht). Meiner Meinung nach bräuchte es auch da Änderungen an mindestens zwei Stellen: Einmal musst Du eine Klasse (Karte) erstellen, auch wenn das bei Multiple Dispatch, wenn ich mich recht erinnere, nur ein mehr oder weniger leerer Rumpf ist (Änderung 1). Außerdem muss mindestens eine Methode geändert werden (Änderung 2). Und da ich gedacht habe, dass Du keine unlösbare Aufgabe stellst und - wenn auch nicht explizit - sagtest, dass sei mit Multiple Dispatch möglich, hab ich es auf eine Uneindeutigkeit geschoben und geändert.
und insbesondere hast du folgendes verletzt: "ohne Nutzung einer Library, die multiple dispatch emuliert".
Das musst Du mir bitte näher erklären, das verstehe ich nicht wirklich.
Denn sollte stimmen, was ich glaube, was Du damit sagen möchtest, kann und will ich Dir zwar gar nicht widersprechen. Dann wäre diese Anforderung aber "für die Katz'". Klar, ich kann mir immer definieren, was eine "Library" ist. So können schon zwei Methoden, die eine bestimmte Aufgabe lösen sollen, eine Library sein. Und auch kann man sagen, dass "Vergleiche x mit y" eine Emulation von Multiple Dispatch ist. Sinnvoll ist das für mich aber nicht. Sprache, insbesondere allgemein verbreitete/verwendete, dient der Differenzierung verschiedener Sachverhalte. Alles andere ist nur verwirrend. Kläre mich also bitte auf. Ich lasse mich auch sehr gern eines Besseren belehren und nehme alles bisher gesagte zurück.
Was du im Grunde getan hast ist ein einfaches "Scoringsystem" zu implementieren und einen eigenen Parser geschrieben, der Anhand festgelegter untypisierter Eigenschaften entsprechende Funktionalität ausführt (hier z.B. einfach Anhand von Vergleichen (bzw. dem Finden) von Strings in Arrays).
Ja, wenn Du möchtest, darfst Du das so nennen, auch wenn ich persönlich das in diesem Kontext als verwirrend empfinden würde. Ich kriege es aber gerade ehrlich gesagt nicht hin, hier den Punkt zu finden, auf den Du hinaus möchtest.
Das geht natürlich und soetwas kann man in jeder Turing-vollständigen Sprache machen, es arbeitet aber um die Sprache herum, d.h. du hast quasi eine "Sprache in einer Sprache" implementiert.
Auch das darfst Du so nennen, wenn Du möchtest. Mit dieser Argumentation könnte man aber wirklich so ziemlich alles "Sprache in einer Sprache" nennen.
In Sprachen die multiple dispatch ermöglichen, ist dieses Drumherumarbeiten hingegen nicht nötig.
Auch hier bitte ich um eine Erklärung, weil nun folgendes Beispiel mir überhaupt nicht erklären kann, was Du damit ausdrücken möchtest. Im Gegenteil erscheint es mir so, dass Du gerade genau gegen Multiple Dispatch argumentierst (siehe dazu auch weiter unten, auch wenn Du dort bereits auf "ausdrucksstarke Sprachen" zu sprechen gekommen bist; da das alles aber fließend ineinander übergeht, vermute ich, es steht in Zusammenhang zueinander).
Das ist etwas abstrakt, aber hier ein Beispiel, das es vielleicht etwas klarer macht, warum du "um die Sprache drumherum gearbeitet" hast: nehmen wir an jemand fügt eine neue Karte hinzu und ändert dein Array und ergänzt es um 'zertrümmern' => 'hart (oder irgendwas anderes)'. Was passiert? Es ändert sich das Verhalten von Karten, die überhaupt nicht betroffen sein sollten, es kann sogar zu logischen Fehlern führen (z.B. wenn für eine Karte gar kein Eintrag im Array ist).
Nein, kann es meiner Meinung nach nicht. Erstens ging es um ein Lehrbeispiel und zweitens um etwas realitätsnahes, was verständlich rüberkommt.
- Die einzelnen Spielobjekte sollen realitätsnahe Eigenschaften bekommen. Diese gelten auch außerhalb des Spiels bzw. in einem anderen Kontext (Ein "Stein" ist "hart", egal ob im Spiel oder in der Realität; ja, ich weiß, es gibt auch "weiche" "Steine", das spielt aber doch für diese ganz abstrakte Veranschaulichung keine Rolle).
- Die einzelnen Spielobjekte sollen realitätsnahe "Angriffe" erhalten, welche auch außerhalb dieses Kontextes gelten (Ja, eine Schere muss auch nicht spitz sein...)
- Die Korrelationen sollen "echte physikalische Gegebenheiten" oder so was in der Art erfassen und diese auch außerhalb des Spiels beibehalten (Ja, etwas "flexibles" wickelt nicht zwingend etwas "hartes" ein...)
Von der technischen Seite her: Wenn für eine Karte kein Eintrag im Array ist, beeinflusst das die Funktionsweise keineswegs, wenn ich im Beispiel keinen Fehler gemacht habe. Findet man im Korrelations-Array den entsprechenden "Angriff" nicht, so führt er schlicht und einfach ins Leere. Gibt es dort eine bestimmte Eigenschaft nicht, so führt ein möglicher Angriff ins Leere. Und das ist so gewollt, wie zuvor hoffentlich verständlich beschrieben.
Wie würdest du dem begegnen? Richtig, du würdest Prüfungen machen, die dafür sorgen, dass jemand, der diese Funktionalität nutzt, nichts "logisch Falsches" eintragen kann, höchstens etwas "fachlich Falsches". Wenn du das vernünftig umsetzt, dann hast du nichts anderes getan als einen Parser zu schreiben, der die Struktur von deinem (immernoch recht einfachen) Array oder allgemeiner ausgedrückt deiner verwendeten Datenstruktur analysiert und validiert und dann die Eingaben in unterschiedliche Funktionalität umsetzt. Ups, das ist ja genau das, was ein Compiler macht.
Nö, für solch ein Szenario (Lehrbeispiel) braucht man keine weiteren Prüfungen. Wahrscheinlich nicht mal in einem praxisnahen Beispiel. Blödsinn und Fehler kann man immer machen, da hilft auch die beste Prüfung nichts. Wenn da einer reinschreibt "Fußgänger überfährt Auto" soll er das machen. Kann ich eh nicht ändern. Ist seine Entscheidung. Und wenn jemand der Prüffunktion was übergeben möchte, was nicht von "Spielobjekt" abgeleitet wurde, gibt's halt nen Fehler. Wie vorher schon gesagt: Es sei Dir unbenommen, dass "Parser", "Compiler" oder wie-auch-immer zu nennen. Sinnvoll ist das meiner Meinung nach nicht.
Dein Ansatz und Bauchgefühl ist somit völlig richtig! Du hast instinktiv gespürt, dass diese Sprache nicht mächtig genug ist, um deine Gedanken in ihr auszudrücken. Du hast daher die Sprache so erweitert, dass sie ausdrucksstärker wird. Das zeigt, dass du ein gutes Gespür dafür hast, ob du deine Gedanken 1:1 in eine Sprache übertragen kannst oder eben nicht. Vielen fällt es nichteinmal auf, dass sie um ihre wirklichen Gedanken "drumherum" arbeiten.
Spätestens jetzt habe ich wirklich etwas den Faden verloren, was Du mir sagen möchtest (ich komme jetzt zu dem, auf was ich voher schon verwiesen hatte). Eindeutig widersprechen kann ich Dir, dass "diese Sprache nicht mächtig genug ist, um deine Gedanken in ihr auszudrücken". Wie man - so hoffe ich jedenfalls - erkennen kann, ist diese Sprache mächtig genug, dass ich meine Intention mit ihrer Hilfe widerspiegeln konnte. Zumindest Matthias und Du scheinen ja meine Idee nachvollzogen und verstanden zu haben. Sozusagen q.e.d. Dass ich die "Sprache so erweitert [habe], dass sie ausdrucksstärker wird", bezweifle ich nicht. Das ist aber die Voraussetzung für Programmierung. Man muss mit der Sprache arbeiten. Programmiersprachen, (die nicht nur einzig und allein eine Aufgabe erfüllen,) müssen abstrakt sein. Und jeden Algorithmus, den man schreibt, kann man als "Sprache in der Sprache" oder "Erweiterung" oder "Library" bezeichnen. Aber was hat das mit "drumherum" zu tun? Ist es nicht viel mehr "mit"?
Außerdem (auch darauf kommst Du gleich noch zu sprechen): Wie ist das bei Multiple Dispatch (habe gerade extra nochmal bei Wikipedia reingeschaut)? Ist es intuitiv und entspricht es weitgehend Deinen Gedanken, dass Du eine abstrakte Klassendefinition, eine abstrakte Methodendefinition und eine "kryptische" Methodenimplmentierung angeben kannst, um "blaues Auto" zu sagen? Ich vermute eher nicht. Und das ist auch gar nicht schlimm, es ist eine Konvention. Ich glaube auch, dass Multiple Dispatch in einigen Bereichen sinnvoll ist, aber halt nicht immer und überall. Es gibt nun mal nur"optimale" (im Sinne von: zufriedenstellende) Lösungen, keine "perfekten" (im Sinne von: besser geht's nicht"). Hast Du natürlich auch nicht behauptet, ich musste es aber gerade loswerden ;-)
[Dein Lob habe ich übrigens erkannt und dankend angenommen, auch wenn es nicht so anhört. Kann ich übrigens nur zurück geben, Du hast mich richtig zum Nach- und Überdenken angeregt.]
Ein gutes Beispiel sind auch Arrays oder Listen. [Beispiel entfernt]
Aber sind das wirklich die Gedanken, die man hat? Denkt man wirklich "mach eine Variable i und gib ihr den Wert 0, dann guck dir die Liste der Dateien an und hol dir die Anzahl deren Elemente, zieh davon 1 ab und solange Variable i kleiner als diese Anzahl ist tue... usw. Nicht wirklich oder?
Nein, natürlich nicht. Da gebe ich Dir recht. Aber wo ist das Problem? So funktioniert jede Sprache nun einmal, sonst wäre es keine Sprache. Eine Sprache ist einfach eine Konvention, um anderen "Objekten" (im Normalfall: anderen Menschen) seine Gedanken verständlich zu machen. Ich muss auch bei der "natürlichen Sprache" Umwege in Kauf nehmen und mit der Sprache arbeiten. Alles andere würde nicht funktionieren, keiner würde mich verstehen oder neue Gedanken könnten nicht gedacht werden.
Eine Sprache sollte die eigenen Gedanken möglichst 1:1 widergeben, sodass Quellcode leicht verstanden und verändert werden kann. Die Aufgabe eines guten Entwicklers ist es dann, ein Problem richtig zu verstehen und es dann mithilfe der Sprache als Werkzeug zu formalisieren.
Da stimme ich Dir zu 100% zu. Ich glaube sowieso, dass wir beide ähnliches meinen und doch etwas anderes sagen bzw. schreiben. Ein Fehler unserer Sprache ;-) Aber einfach nur "Ente" zu sagen bringt uns auch nicht weiter.
Entschuldigt bitte, dass das jetzt so lang geworden ist. Kürzer hat es unsere Sprache aber leider nicht zugelassen. Ich freue mich jedenfalls auf Deine Antwort. Noch schöner fände ich allerdings, wenn wir statt technische oder sprachliche Dinge zu diskutieren, Matthias gemeinsam mit allen anderen bei seinem Vorhaben unterstützen.
Gruß, der T-Rex hat noch nix zu meiner zweiten Grußzeile gesagt, Dennis
Ps: Wo ich meinen Text gerade nochmal in der Vorschau gelesen habe: Manches ist nicht ganz so toll formuliert, Whouzuo, es ist aber nichts auch nur im Entferntesten böse gemeint!