[linux-l] LinuxScript?

Steffen Dettmer steffen at dett.de
Mo Apr 1 17:20:45 CEST 2002


* Oliver Bandel wrote on Mon, Apr 01, 2002 at 14:29 +0200:
> On Sun, 31 Mar 2002, Steffen Dettmer wrote:
> > * Oliver Bandel wrote on Sun, Mar 31, 2002 at 21:29 +0200:
> > Da die Eigenschaften sehr ähnlich sind, würde man hier jedoch nur
> > eine ziemlich flache Vererbungshierachie hinkriegen, kann mir
> > nicht vorstellen, daß sowas sehr viel bringt. 
> 
> Vererbung ist zwar das, was alle immer gleich mit OO verbinden.

Ja, Benutzerdefinierter Datentyp, Vererbung und Polymorphie sind
doch die Kriterien für Objektorientierung. IIRC. Achso, und
natürlich Datenkapselung bzw.
Interface-Implementierungs-Trennung, Geheimnisprinzip oder wie
auch immer man diese Kapselung/Schichtung/Trennung nennt.

> Zu OO gehört mehr als nur Vererbung, leider wird immer, wenn
> man OO anführt, auch quasi reflexartig an Vererbung gedacht.

Ja, ohne Vererbung keine Polymorphie. Ohne Vererbung und
Polymorphie bleibt nur Benutzerdefinierter Datentyp. Das ist ja
auch z.B. ein struct. Und dieser sicherlich nicht
objektorientiert :)

> Aggregation etc. ist aber oftmals sinnvoller als Vererbungs-Fanatismus,

Na ja, kommt auf das Problem an. Ein "ist-ein" schreit nach
Vererbung, ein "hat-ein" schreit nach Aggregation...

> > Natürlich kann man sockets von files ableiten und die
> > Socket-Eigenschaften hinzufügen. Aber in der Praxis braucht man
> > sowas eher selten.
> 
> Tja, man sollte eben nicht immer gleich alles voneinander
> ableiten/vererben wollen... :)

Hier ist das ja richtig, denn ein Socket ist ein File. Kann nur
bißchen was spezielles mehr. Und ein TCP oder UDP Socket ist ein
Socket, kann nur wieder ein bißchen mehr. Paßt schon. Macht nur
nicht so sehr in der Form Sinn, finde ich. Wenn man das sauber
macht, hat man dann sowas wie ACE oder sowas, schön und
objektorientiert, aber nun wirklich nicht mehr Systemteil...

> > Na ja, ich gebe jedoch zu, sogar selbst sowas
> > schon gebaut zu haben :)
> 
> So, so... ;-)

Aber wie angedeutet, daß ist dann in meinen Augen eine höhere
Schicht als "OS". Natürlich könnte man sowas in die
Standardbibliotheken oder theoretisch noch tiefer ins System
integrieren. Kommt vielleicht noch. Java hat ja damit ganz gut
angefagen - hier gibt's sehr umfangreiche Bibliotheken. Das hat
schon so seine Vorteile.
> 
> > > Ebenso könnte man auch das Objekt Prozess nach dem pwd/cwd (getcwd()),
> > > seiner ID, etc. befragen.
> > 
> > Sicherlich die Instanz eines Prozesses. Aber macht erst wirklich
> > Sinn, wenn es dann "Kinder" gibt, die spezielle Eigenschaften
> > haben, die jedoch nicht immer interessieren, so daß man
> > beispielsweise Polymorphie ausnutzen könnte...
> 
> Wie meinen?

Na ja, wenn man 100 Instanzen von Prozessen nach irgentwas
handhabt, funktioniert das auch mit nicht-objektorientierten
Datentypen - also z.B. structs - ganz prima. Die kann man dann
auch in ein Modul packen. Dann hat man einen prima
benutzerdefinierten Datentyp (mit Kapselung), ganz ohne OO, und
das würde prima funktionieren. Würde ich vermutlich lieber in C++
bauen (wegen der Luxus-Syntax und strengen Typprüfung), und hier
vermutlich ne Klasse definieren. Aber das ist ja dann nicht
wirklich objektorientiert, weil man eben die Merkmale der
Objektorientierung überhaupt nicht wiederfindet. Es sieht zwar
vielleicht so aus, weil da "class" steht, aber ohne Vererbung und
Polymorphie ist es eben *nicht* OO. 

> > Eigenschaften zu haben, ist kein hinreichendes Kriterium für
> > Objekt/Klassenkandidaten, finde ich.
> 
> Sage ja garnicht, daß das hinreichend ist.
> Finde es dennoch schnuckelig, wenn ich das Directory
> fragen kann, wieviele Files es hat, oder wenn ich
> die Files fragen kann, ob sie schreibgeschützt sind...

Kannst Du doch auch ohne OO. In C würde ich sowas machen:

/* Headerfile */
int getDirectoryFiles(void);

/* C File */
/* typedef struct Directory {...} */
static Directory dir_;

int getDirectoryFiles(void)
{
	return dir_.fileCount;
}

static void somePrivateMethod(void)
{
	//cannot be called from outside
}


Ich hab einen benutzerdefinierten Datentyp, Geheimnisprinzip
(schließlich kommt man nicht direkt an dir_ ran, gibt nur ein
paar "getter" und andere Methoden; gibt auch ne Unterscheidung
zwischen "public" und "private" Methoden). Man kann dann das
Directory fragen, wieviele Files es hat. Zusätzlich kann man
natürlich statt einem einzigen "static Directory dir_;" auch ne
Liste oder ein Array anlegen, klar, falls man mehrere braucht.
Ich würde aber eher machen:


/* Headerfile */
/* typedef struct Directory {...} */

Directory *newDirectory(void);
int getDirectoryFiles(Directory *this);

/* C File */
Directory *new(void)
{
	Directory *this = malloc (sizeof(Directory));
	this->memberValue = "inital values...";
	return (this);
}
int getDirectoryFiles(Directory *this);
{
	return this->fileCount;
}

static void somePrivateMethod(Directory *this);
{
	//cannot be called from outside
}


Dann kann man schreiben:
Directory *dir = newDirectory();
getDirectoryFiles(dir);

Man kann auch noch Funktionspointer in den Struct miteinbauen,
dann kann man schreiben:

int count = dir->getFiles();

Alles C. Sieht zwar schon für manche nach OO aus, ist es aber
nicht.

In C++ (ohne OO) kann man das Directory-Headerfile in einem

/* typedef struct Directory {...} mit Funktionszeigern*/
namespace Directory 
{
  /* Headerfile */
  Directory *new(void);
}

dann kann man sogar schreiben:
Directory *dir = Directory::new();
int count = dir->getFiles();

Sieht doch wirklich schon sehr nach OO aus - ist es aber trozdem
nicht. Und so wird es ja in C auch oft gemacht. Vielleicht nicht
mit Funktionszeigern, aber es wird gemacht. Leider umgeht das
etwas das Geheimnisprinzip, weil ich ja im letzen Fall z.B.
schreiben kann:

Directory *dir = Directory::new();
int count = dir->privateMemberFileNumber;

Weil ich ja (leider) auch direkt auf den Struct zugreifen kann.

> Ich sage ja nicht, daß man das gesamte drunter liegende System
> neu schreiben soll. Eine weitere Schicht/Sprache/Scriptingmöglichkeit
> wäre aber was feines.

Gibt's doch: Perl Modules, ACE, Java,... Die machen ja im Prinzip
nix anderes; nur das nur Perl eine Scriptsprache ist.

> Also nicht alles umkrempeln, sondern was oben drauf stülpen.

Ja, sowieso, klar.

> > Eigenschaften kann man auch
> > sehr gut über klassische Datentypen handhaben, also ein C-Struct,
> > dessen Instanz in einem Modul lebt. Natürlich ist sowas technisch
> > gesehen ziemlich genau eine Klasse. Ich meine ja nur, es gibt
> > hier nicht unbedingt notwendigerweise einen Bedarf.
> 
> Meine ich ja auch nicht, daß es Bedarf gibt...
> aber vielleicht Bedürfnis? ;-)

Na ja, ich weiß nicht, warum? Es geht ja genau so in z.B. Perl,
nur das eben die Syntax anders ist. Im Prinzip das gleiche. Na
gut, tolerante Parser (die "noise" wie "the" oder "a" massiv
erlauben), sind schwer gut zu kriegen. Sieht man auch bei Perl.
Manchmal "vermutet" der Parser eben mal nicht das, was man
eigentlich meinte. Deshalb sagt man Perl* auch öfter mal "... is
noise and should be ommited.". Hat sich eben mehr bewährt, weil
die Fehlermeldungen treffender werden, sicherer sind usw.

>  (Aus der BWL-Vorlesung weiß man noch: Bedarf = Bedürfnis + Kaufkraft) :)

Ach so, na ja, sowas hatten wir nicht :) Also meinte ich
Bedürfnis.

> Also, zumindest wenn man nicht immer wieder das Rad in C neu
> erfinden will, also eher high-level programming machen will,
> bietet sich eine ergänzende Schicht an.

Na, warum denn C in Unix? C ist doch so umständlich, unflexibel
und typunsicher. Da kann man meistens C++ nehmen, gibt's ja für
Unix :). Und für C++ gibt's ja dann ACE usw. Das ist natürlich
jetzt nicht das richtige Beispiel, weil das schon wieder viel zu
genial und damit nicht trivial einsetzbar ist. Aber die Richtung
stimmt ja :)

> Ich meine wirklich funktional.
> 
> Prozedural ist's, was man in C macht. Funktional ist's, wie
> man in Scheme/Haskell/... macht.
> OCaml btw. ist prozedural, funktional und OO. Wird Zeit, daß
> O'Reilly endlich mal die englische Fassung des Ocaml-Buches
> herausgibt.

Jetzt hab ich sicherheitshalber selbst mal nachgegeuckt. Hab z.B.
folgendes gefunden:

1. Alle Programme und Prozeduren sind Funktionen, die eine klare
   Unterscheidung zwischen Eingabegrößen (Parameter) und
   Ausgabegrößen (Resultate) vornehmen.

2. Es gibt keine Variablen oder allgemeine Zuweisungen. Variable
   werden mittels Parameter realisiert.

3. Es gibt keine Schleifen. Zyklische Abläufe werden durch rekursive
   Aufrufe realisiert.

4. Der Wert einer Funktion hängt nur vom Parameterwert ab und nicht
   von der Verlaufsform innerhalb der Funktion (referentielle
   Transparenz).

5. Funktionen stellen selbst Werte dar (als sogenannte first-class
   values). Es gilt das Substitutionsprinzip. 

Beispiele: OPAL, ML bzw. Standard ML , HASKELL, MIRANDA oder
GOFER (kenn ich alle nicht).

(nach: ivs.cs.uni-magdeburg.de/sw-eng/agruppe/lehre/psk.shtml)

Prozedural ist also das, wo es dann schon Luxus wie Schleifen und
so gibt (wie Du ja auch sagst: C).

> (Ruby soll wohl auch - und mittlerweile auch Python - funktionales
>  Programmieren ermöglichen. Ein Grund, sich diese Sprachen vielleicht
>  doch mal anzuschauen :))

Aber eigentlich müßte man dann ja auch in C funktional
programmieren können: eben, wenn man keine Schleifen und
Variablen verwendet. Aber bringt das was? Ich meine, hat das
Vorteile? Natürlich kann man Schleifen durch Funktionsaufrufe
ersetzen etc., und das sicherlich eleganter, als es in C möglich
ist, aber was bringt das unterm Strich?

> > > fälschlicherweise benutzt wird für das, was man in C und Co. so
> > > verbricht; ich denke da eher an Scheme, Haskell, OCaml etc.).
> > 
> > Kenn die Leute leider nicht.
> 
> Welche Leute kennst Du denn?
> C, C++ Perl, Python?

Python auch nicht. 

> > > Aber OO in Massen hat noch niemandem geschadet, 
> > 
> 
> Scheiss neue deutsche Rechtschreibung.
> Ich meinte in Maßen, also im Sinne von maßvoll.

Ach so :) Ist ja CooL :) Stimmt, also im Maßen, ja? Was macht man
eigentlich in solchen Fällen nach neuer dt. Rechtschreibung?!

> Massenweise hat OO bestimmt sehr wohl schon Uneil angerichtet. :)

:) Yep, auf jeden!

> > Das ist dann meist mehr verwirrend und
> > ärgerlich.
> 
> Dahinter sind dann die Leute zu fineden, die bei Stellenangeboten sagen,
> daß sie C++ können, woraufhin der Personal-Fuzzi denkt,
> der Bewerber habe Peilung von OO.

Ja, so ungefähr. Hab auch schon so Merkwürdigkeiten erlebt. Zum
Beispiel jemand, der (angeblich) C kann, aber "printf" nicht
kannte. Na, sowas wundert einen dann schon. Das ist sowieso ein
deprimierendes Thema. Hab mal mit einem MSCE für Netzwerke
gearbeitet, der hat selbst nach dem zweiten Mal der Erklärung
immer noch nicht gepeilt, daß bei einem Hub ne Lampe leuchtet (so
fern dran :)), wenn man das *richtige* Kabel einsteckt. Er hat
zwar immer genickt, wenn ich was von crossover Kabeln erzählte,
aber die dann nächste Mal trozdem wieder angebaut...

> > Sinnvolle OO Abstraktion ist eine Kunst,
> 
> Gutes Programmieren ist auch prozedural eine Kunst.
> Wie bei jeder kunst: Man lernt nie aus (und genau das ist
> ja die Kunst daran!)

Na ja, und es gibt 1000 funtionell gleiche Wege, von denen aber
nur eine Handvoll schick, elegant etc. ist. Manche haben aber
irgentwie das Talent, genau die merkwürdigste Methode der 1000
möglichen zu wählen, na ja...

> struct dirent * readdir( DIR * directory )
> 
> Liefert Dir die Einträge des Direktory nacheinander
> zurück.
> Sind die Inhalte eines Directory etwa die Eigenschaften
> des Aufrufers?

Ja, der Aufrufer hat hier die "Macht". Er kann den return-Value
überschreiben (ist ja kein "struct dirent *const readdir"), er
muß *directory beschaffen etc.

> Man könnte auch sagen: sende die Message readdir an das
> Objekt directory.

Directory ist eindeutig ein Datenfluß, kein Kontrollfluß.
Außerdem hat readdir nicht die Fähigkeit, auf allgemeine
Nachrichten zu reagieren (es "ist" kein "Nachrichtenverarbeiter".
In java würde er also das Interface nicht implementieren, bzw. in
C++ nicht beerben). Also geht kein readdir.handleMessage oder
sowas. Könnte man aber bauen, klar.

> Naja, könnte man noch lange drüber philosophieren.
> Ist dann letztlich eine Sache der Betrachtung.

Ja, sicher, aber das finde ich interessant. Meistens kommt man ja
gar nicht dazu. Hin- und wieder ist es aber bestimmt ganz
nützlich, auch mal über die Grundfesten nachzudenken. Sonst wird
man später vielleicht selbst einer, der sinnlos oder falsch OO
oder sonstwas verwendet. Ich meinte, das übt ja und fördert das
Verständnis. Sowas vergißt man ja auch schnell.

> Ja, prozedural nennt man das typische C-geprogrammiere.
> Funktional sind Sachen wie in Haskell, hier z.B. Quicksort
> in Haskell programmiert:

Müßte in Prolog dann auch ganz gut gehen. Ist Prolog vielleicht
funktional? Nee, glaub nicht. Hab Prolog aber auch schon wieder
vergessen - leider! Konnte man witzige Sachen mit machen.

> qsort :: [Int] -> [Int]

Ne Art Deklaration?

> qsort [] = []

Was heißt das?

Quicksort war "Teile-Und-Herrsche", bis man über zwei Elemente
herrscht, die man ggf. austauscht, und dann sortierte man die
geteilten (und inzwischen sortierten) Ketten, richtig? Oder
verwechsel ich das schon wieder?

> qsort (x:xs) = qsort [ y | y<-xs, y <=x] ++ [x] ++ qsort [y | y<-xs, y > x ]

Verstehe ich überhaupt nicht, kenn auch die Syntax überhaupt
nicht. Ach so, moment, Du suchst Dir irgentwo ein X, packst links
alles hin, was kleiner ist, und rechts, alles was größer ist, ja?
Was macht hier xs eigentlich? Erklär mal, sieht nett aus :)

> Sieht bedeutend besser aus, als Quicksort in C. :)

Irgentwie kompakter :)

> ein Ergebnis. Es ist völlig unerheblich, ob die Argumente
> und returnvalues nun Variablen im klassischen Sinne sind,
> oder ob es Funktionen selbst sind.

Ahh ja, genau so war das. Hab ich nie benutzt, glaub ich. In der
Praxis wohl auch seltener zu finden. Eine ideale
Programmiersprache müßte es gestatten, sozusagen "sauber zwischen
den Konzepten zu wechseln", wie man es gerade braucht. Also das
ich z.B. in ne OO Methode ein funktionales "Teilprogramm" haben
dürfte. Aber sicherlich schwer bis gar nicht realisierbar.

> Man kann also Funktionen
> schreiben, die Funktionen zurückliefern und diese kann man
> dann als Argumente an andere Funktionen übergeben.

Ja, dann muß man nur die "Regeln" aufschreiben, und die
"Ablaufsteuerung" ergibt sich daraus. Meistens jedenfalls :)

> Coredumps kann es prinzipiell nicht geben.

Na gut, die gibt's ja nur, weil C sich defaultmäßig nicht um
SIGSEGV kümmert, und es sowas überhaupt geben darf. In meinen
Augen ist das aber nur ne Abschaltung theoretisch geforderter
Sicherheit, um ein bißchen Performance zu gewinnen. Java kennt
solche Probleme ja auch nicht, oder Ada, aber beide sind doch ein
bißchen langsamer, weil eben mehr zur Laufzeit gemacht werden
muß, als: "Nimm da mal vier Byte (was auch immer das ist), und
interpretiere das mal als ne Ganzzahl, in der Hoffnung, daß
jemand vorher da auch wirklich ne Ganzzahl hingeschrieben hat.".
Ist ja auch mehr "Versprechen-Und-Glauben" als Programmieren :)

["Versprechen-Und-Glauben" ist CooL, glaub' ich, sollte man sich
mal merken :)]

> (Sie treten höchstens
> auf, wenn die Implementierung selbst nicht ok ist - die Sprache selbst
> ist ja oftmals noch in C geschrieben => da geht schon mal was schief...

Na ja, das ist ja hier unerheblich.

> aber ist die Implementierung sauber, kann man keine Coredumps
> durch dumme Programmierung hervorrufen. In C kann man das mit einem
> Einzeiler (sofern's ulimit nicht auf 0 gestzt ist...).).

Man *kann* das auch in C verhindern / behandeln. Theoretisch. Ist
auch gar nicht so schwer zu kapseln. Man hat dann einen SigSegv
handler, der nur ein Flag setzt, und jede Funktion prüft das Flag
(so ziemlich ständig). In C++ kann man dann ne PointerException
schmeißen. Geht auch mit Smartpointern ganz gut. Nur leider kann
man sich ja nicht mal auf SigSegv verlassen, denn es kommt ja
nur, wenn man wirklich in den Wald schießt. Liegt das was
anderes, falsches, dann kommt es ja leider wieder nicht. Also
kriegt man es (ohne exclusive Verwendung von Smartpointern) nie
sauber, nur ein bißchen "suaberer" hin, da kann man es meistens
ganz lassen und gegen efence linken :) Na ja, C ist eben schnell.
Nicht schön.

oki,

Steffen

-- 
Dieses Schreiben wurde maschinell erstellt,
es trägt daher weder Unterschrift noch Siegel.



Mehr Informationen über die Mailingliste linux-l