[linux-l] Ocml vs. Java

Volker Grabsch vog at notjusthosting.com
Fr Okt 21 01:50:54 CEST 2005


On Sun, Oct 02, 2005 at 02:57:19PM +0200, Oliver Bandel wrote:
> On Sun, Oct 02, 2005 at 12:55:27AM +0200, Volker Grabsch wrote:
> > On Mon, Sep 26, 2005 at 04:38:28AM +0200, Oliver Bandel wrote:
> > > [...]
> 
> [...]
> > Außerdem: Schon prinzipiell packe ich nichts in eine Liste, von dem
> > ich 1. im Voraus die Größe nicht abschätzen kann und 2. nur
> > sequentiellen Zugriff brauche. Das ist für mich eine Grundregel des
> > gesunden Programmierer-Verstands.
> 
> 
> Wenn klar ist, daß es bei der Funktionalität bleibt...
> 
> 
> ...so manches Tool wird aber früher oder später größer...
> ...und dann braucht man doch wieder die Sachen als Datenstruktur,
> weil man ggf. mehrere Passes braucht.

Wenn man ständig hin- und herlaufen muss (z.B. beim Sortieren),
dann kann man ja immer noch den Iterator in eine Liste "abkippen".

Wenn jedoch schon ein Mehrpass-System reicht, würde ich die
Schichten direkt hintereinander packen, d.h. sowie die erste
Schicht ihre Einträge erzeugt, werden sie von der zweiten gleich
weiterverarbeitet.

Auch hierfür braucht man nur Iteratoren, gerade funktionale Features
(+Closures) ermöglichen doch diesen Weg. Deshalb verstehe ich nicht
ganz, wieso du dich so sehr dagegen sträubst. Zumindest in Python
sind Iteratoren teilweise sogar noch einfacher zu handhaben als Listen.

> [...]
> > Dass ich nen Iterator brauche. Außerdem wollte ich nen "funktionaleren"
> > Ansatz von dir.
> 
> Hmhhh... mal sgats Du, es macht keinen Sinn die Sachen in OCaml
> nachzbilden, dann wieder willst Du es funktionaler.
> 
> 
> Kannst ja mal schauen:
[...]
> Meinst Du es so?!

Hmmz .. irgendwie reden wir da aneinander vorbei. Aber egal, ich muss
mir Ocamls Stream-Zeugs einfach mal reinziehen. Hätte ja sein können,
dass du diese Architektur schon kennst und verwendet hast.

> > Die Architektur des
> > gesamten Systems ist das Innovative. Die konkreten Parser könnten
> > theoretisch auch jeder in einer anderen Programmiersprache unter
> > anderen Paradigmen geschrieben sein. :-)
> 
> Aber vermutlich viel aufwäniger.
> 
> Gerade was so Parserei, Datenstrukturen usw. angeht, sind doch FPLs
> gut geeignet. Da kann man recht einfache Formulierungen für die
> Probleme finden.

ACK. Übrigens gibt es eine ganz hammerharte extrem-restriktive FPL,
die sehr, sehr streng funktional ist .. aber die man vielleicht nicht
mehr "Programmiersprache" nennen kann: XSLT.

Damit kannst du Baumstrukturen ineinander umwandeln, also ein XML-Format
in ein anderes. Zum Beispiel das Wiki-XML-Format nach XHTML oder nach
TeXML. XSLT kann aber aus XML-Dateien auch Text erzeugen, d.h. ein
notdürftiger Wiki-XML => LaTeX  Konvertierer ist auch recht schnell
erledigt.

XSLT ist eine Transformations-Sprache, was man (in Bezug auf
Eigenes-XML-Format => XHTML) ebenfalls als "Stylesheet" interpretieren
kann.

Ich will jetzt nicht weiter ausholen, sonst müsste ich ein XSLT-Tutorial
schreiben, sondern wollte nur, dass du weißt, dass es sowas gibt.

XSLT ist leider auch nur ein (verboses) XML-Format, aber wenn sowieso
eine XML-Datei erzeugen willst, ist das ne feine Sache, weil du keine
2 Sprachen miteinander mischen brauchst.

Das einzige, was von der Sauberkeit her über XSLT kommt, sind
XML-Konstrukte in anderen Programmiersprachen, also wenn man z.B.
*nicht* das hier schreiben muss:

	print "<?xml version=\"1.0\"?>"
	print "<html>"
	print "  <body>Text</body>"
	print "</html>"

sondern sowas hier schreiben kann:

	print_xml(
	    xml.HTML(
	        xml.BODY("Text")
	    ))

(etwas ähnliches gibt es für Ruby und auch Python, und glaube, es auch
für Ocaml gesehen zu haben ... in gewisser Weise findet man diesen
Ansatz auch in jedem HTML-Templating-System)

Dennoch: Für einfache Transformationen hat XSLT vorallem den Vorteil,
dass es ein stabiler Standard ist, d.h. praktisch überall und auch
in Zukunft funktionieren wird.


> [...]
> > > Ich mache das ganz gerne, daß ich mir immer erst mal alles in den RAM
> > > lese, Datenstrukturen aufbaue und dann damit arbeite.
> > > Das hat nämlich den Vorteil, daß man die Datenstrukturen auch mehrfach nutzen
> > > kann und nicht immer wieder die Datei neu einlesen.
> > 
> > Wenn ich nen Algorithmus habe, der den Datenbestand sequentiell
> > durchlaufen kann und dabei effizient arbeitet und nur wenig Speicher
> > verbraucht, dann implementiere ich *diesen* und keinen anderen.
> 
> Naja, wenn es bei dem speziellen Anwendungsfall bleibt, ist das auch ok.

Wenn nicht, kann ich es immer noch *danach* in eine Liste kippen.
Und denn der Algorithmus die Daten irgendwann nicht mehr sequentiell
erzeugt, kann ich immer noch ne Liste nehmen. Der Rest der Applikation
sieht kann ja die Liste genauso gut iterieren.

Und auch umgekehrt: Wenn der Rest der Applikation ne Liste braucht, aber
der der Algorithmus nicht, kann der Algorithmus doch weiterhin effizient
nur nen Iterator füttern, und die Applikation kippt es in eine Liste,
um weiter zu arbeiten. Ist ja kein extra Aufwandt.

Es ist also stabil gegenüber zukünftigen Veränderungen. Wieso sollte man
es nicht machen? Das schöne ist doch (in Python, aber sollte auch in
Ocaml so sein), dass ich wenn ich die Daten seriell erzeuge, einen
Iterator damit füttere, und wenn ich das nicht tue, dann nehm ich
halt ne Liste. Und am anderen Ende dasselbe mit der Traversierung:
Lese ich die Daten seriell, iteriere ich halt (egal, ob es ein Iterator
oder ne Liste war), und wenn nicht, dann sage ich eben "t = tuple(iter)"
und schon kann ich t als Liste verwenden (Tupel sind read-only Listen).

Arbeiten beide Seiten mit Iteratoren, läuft das direkt, effizient ab.
Braucht eine der beiden Seiten ne Liste (oder beide Seiten), dann
geschieht das ebenfalls ohne Fuzz. Was will man mehr?

> > Ich baue also eine Struktur auf, die am Ende nur serialisiert werden
> > braucht. Muss ich sie deshalb im RAM behalten?
> 
> Wenn Du sie mehrfach brauchst?
> Z.B. Einen Brief, aber mit mehreren Empfängern...
> ...willst Du immer den selben Brief mehrfach aufbauen?
> Statt dessen die selbe Datanstruktur nehmen und immer bloß an der
> richtigen Stelle das Adressfeld ändern.

Also erstmal habe ich auch bei Iteratoren diese Freiheit, denn immerhin
kann ich sie ja jederzeit in eine Liste kippen. Wieso sollte ich mich
also von vornherein auf eine Liste festlegen?

Und zum anderen ist das wirklich die Frage der Effizienz: Manchmal
ist es besser, solch eine Liste aufzubauen und mehrfach abzulaufen,
aber manchmal ist es auf andersrum besser: Jedes mal die Liste neu
"aufzubauen". Kommt auf die Größenverhältnisse an.

Wenn die Liste z.B. durch Berechnungen entsteht (z.B. mal ganz blöd
die Fibonacci-Folge), und man 100.000.000 Einträge hat. Und am anderen
Ende bloß zwei Filter hängen, bei denen der erste die Teile zum Drucker
jagt (also nur Serialisierung), und der andere die Liste verdünnt (z.B.
jedes 1.000.000 ste Element anzeigt), dann sollte alles in Echtzeit
passieren. Es wäre kompletter Wahnsinn, hierfür 400 MB RAM zu opfern.

Übrigens hast du noch eine Lösung übersehen: Einen direkten Verteiler.
Das heißt, die Liste wird nur einmal traversiert, aber jedes Element
wird von zwei Funktionen bearbeitet. Mittels Closures ist das kein
Problem. Das sieht dann fast wie Multitasking aus (ein erzeugender
Prozess, und zwei lesende), aber in Wahrheit geht das alles in nur
einem Thread, dank der Closures. Ich meine hier übrigens
"Closures", wie sie in Python/Ruby genannt werden ... ich glaube,
in Ocaml bedeutet "Closures" ein bisschen was anderes.

Das ist jetzt sehr theoretisch, aber technisch eigentlich machbar.
So hat man sauberen Code: Jeder "Prozess" denkt, er durchläuft ne
Iteratorschleife bzw. füttert nen Iterator, aber in Wirklichkeit hat
keiner den Kontrollfluss. Aber okay, das geht jetzt schon etwas zu
weit. Zumal diese Art der Iterator-Behandlung weder in Python noch
in Ruby dermaßen fortgeschritten ist. Aber der Schritt dahin ist
minimal.

> > Ich hab in Ocaml nachgelesen: Diese Art von Polymorphie (Funktionen-
> > Polymorphie) meinte ich überhaupt nicht. Ich meinte die Polymorphie
> > von Objekten.
> 
> Das ist es, wenn ich meine: Bestimmte Herangehensweisen (z.B. OO-Ansatz)
> führt dazu, daß man bestimmte Probleme in einer gewissen Weise lösen
> muß (mit OO-Konstrukten).
> Vermutlich hätte ein grundlegend anderer Ansatz dazu geführt, daß
> Du nicht nach Polymorphie von Objekten ausschau halten musst.

Das kann natürlich sein. Aber ich halte die Augen bei meinen Projekten
sehr weit offen, gerade was auch funktionale Herangehensweisen angeht.
Wiegesagt könnte ich meine Muster bzw. meine Architektur nicht wirklich
in eine der Schubladen "OO" bzw. "FP" stecken.

> > > Naja, das beispiel ist immer so ein typisches.
> > > Ob man in dem Falle OO anwenden sollte... hmhhh.
> > > Kann man schon machen, bzw. wird oft gemacht.
> > > Aber FP-Ansatz mag ggf. auch passen.
> > > 
> > > Könnte man sich echt mal nen Kopp zu machen... ;-)
> > 
> > Ja, aber erfinde das Rad dabei nicht neu. :-)
> 
> Ach nun doch nicht?
> Ich dachte, es macht keinen Sinn, wenn ich die Sachen,
> die Du in Python per OO gemacht hast nochmal reimplementiere.
> Also doch noch ein neues Rad erfinden, statt reimplemntieren.
> 
> Nun also doch nicht neu erfinden?
> 
> Viell. reden wir wieder mal aneinander vorbei.

Vielleicht verdrehst du mal nicht die Wortbedeutungen.
Die Redewendung "das Rad neu erfinden" ist doch komplett ironisch! Man
erfindet dabei nichts Neues.


Entweder du reimplementierst etwas Bestehendes, oder du gehst nen
anderen Ansatz. Beides ist gut.

Aber wenn du etwas Bestehendes reimplementierst, dabei aber gleichzeitig
glaubst, etwas neues zu tun, dann ist dieser Irrglaube sehr
kontraproduktiv, weil er dich daran hindert, die früheren Ergebnisse
du beachten. Du handelst dir alle Nachteile und Probleme einer Erst-
Implementierung ein, obwohl es eigentlich gar keine ist, sondern eben
eine Reimplementierung. Und wenn man sowas macht, also etwas allein vom
Urschleim aufbauen, das gar nicht neu *ist*, dann sagt man, jemand
"erfindet das Rad neu". Und diese viel zu oft beobachtete Manie,
bisherige Lösungen zu ignorieren (die Kernursache des Problems), nennt
man dann das NIH-Syndrom.

Nur, damit klar ist, was ich unter diesen Begriffen verstehe.


Nun zurück zum Thema: Ich meinte, wenn du dir über das Problem
"nen Kopp machst", ist es sehr wahrscheinlich, dass die Lösung, auf
die du kommst, schon seit Jahrzehnten bekannt ist. Diese dann in alle
Einzelheiten auszutüfteln, und dabei über (von anderen längst gelöste)
Probleme zu stolpern, statt einfach mal in der Literatur nachzuschauen,
davor wollte ich dich warnen.

Ganz konkret: Ich glaube, wenn du nach einer Lösung für obiges
Polymorphie-Problem suchst, wirst du zwangsläufig den gleichen Weg
einschlagen wie die OO-Sprachen. Weil es einfach mal naheliegend ist.
Selbst wenn du dich weigerst, es so zu nennen, und vielleicht eigene
Begriffe dafür anbringst, bin ich mir sicher, du würdest von der
Struktur her den gleichen Code produzieren. Und spätestens dann ist
es an der Zeit, doch einfach mal *direkt* die Ocaml-OO-Features zu
nutzen, die dir dann nämlich genau das Problem lösen würden, für das
du gerade selbst was konstruiert hast.


All das meinte ich damit, dass du das Rad nicht neu erfinden sollst.

Natürlich wäre es möglich, dass du einen völlig anderen, neuartigen
Ansatz findest. Aber bei einem so einfachen, typischen Standardproblem
mit einer so naheliegenden Lösung kann ich mir das beim besten Willen
nicht vorstellen. Bei komplizierteren Problemen hingegen gebe ich dir
völlig recht: Da kann ein anderer Ansatz Wunder bewirken.

Ob diese "Wunderwaffe" aber allein aus den FP-Paradigmen besteht, wage
ich doch sehr zu bezweifeln. :-)  Ein bisschen Einfallsreichtum und
Kombinations-Gabe seitens des Programmierers ist auch gefordert. Und
vorallem: Zur Inspiration die Architekturen anderer Systeme anschauen.
Genau das versuche ich persönlich jedenfalls, leider nur mit mäßigem
Erfolg.


> Aber wenn solche Diskussionen sich zu MegaThredas ausweiten und den gesamten
> Tag mit Zeitbedarf in sich hinein saugen, dann ätzt es doch... weil ich da
> dann doch lieber mal wieder was konkret machen wollte.
> 
> Habe mir mal wieder ein projkt heraus gesucht, das ich schon seit langem mal
> bearbeiten wollte; seit gestern habe ich da etwas Muße zu.

Cool, worum geht's denn?


Viele Grüße,

	Volker

-- 
Volker Grabsch
---<<(())>>---
Administrator
NotJustHosting GbR



Mehr Informationen über die Mailingliste linux-l