[linux-l] Ocml vs. Java
Oliver Bandel
oliver at first.in-berlin.de
Do Sep 29 13:44:42 CEST 2005
On Fri, Sep 23, 2005 at 07:03:58PM +0200, Volker Grabsch wrote:
> On Fri, Sep 23, 2005 at 08:09:48AM +0200, Oliver Bandel wrote:
> > > > List.iter2 (fun a b -> print_endline (string_of_int(a + b))) liste1 liste2
> >
> > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >
> > statt: print_endline (string_of_int(a + b))
> > ginge es auch so: Printf.printf "%d\n" (a + b)
>
> Es geht darum, dass inline eine Funktion definiert wird, nämlich:
> (fun a b -> ...)
>
> In Python brauchst du diese Ecke nicht zu denken, und hast stattdessen
> eine Schleife mit Inhalt, was IMHO schneller und leichter erfasst werden
> kann. Wenn das als Schleife dastehen würde, stünden Lister.iter2, liste1
> und liste2 zusammen, statt vom Inhalt unterbrochen zu werden.
Was denn der "Inhalt" ist, ist Ansichtssache.
> Wird der
> Schleifen-Inhalt sogar explzit in eine extra Funktion verpackt, ist das
> nur dann übersichtlicher, wenn der Schleifeninhalt nicht so kurz ist.
>
> Ich geb mal ein Analogon in der deutschen Sprache: Wenn man den Code
> liest, ist es, als würde man einen Satz lesen. Die "Schleife" wird
> in Python zuerst genannt, und danach der inhalt. In Ocaml wird die
> Schleife wie durch einen Nebensatz unterbrochen:
>
> Es werden nun zwei Listen durchlaufen, deren Elemente paarweise
> addiert und ausgegeben werden, bezogen auf die Listen "liste1"
> und "liste2".
>
> In Python sieht das eher so aus:
>
> Es werden die Listen "liste1" und "liste2" durchlaufen. Ihre
> Elemente werden paarweise addiert und ausgegeben.
>
> Letzteres finde ich besser lesbar. Das spricht übrigens nicht
> grundsätzlich gegen funktionale Sprachen. In Ocaml z.B. würde man sehr
> viel Lesbarkeit gewinnen, wenn die Argumente einfach nur eine andere
> Reihenfolge hätten:
>
> List.iter2 liste1 liste2 (fun a b -> print_endline (string_of_int(a + b)))
>
> Mmmmhh ... schon viel besser. :-)
Aha.
naja, zum Glück ist OCaml ja eine funktionale Sprache (eigentlich
Multiparadigmen-Sprache, aber hier interessiert ja das funktionale Konzept):
Wenn es einen *wirklich* sehr stören sollte.... macht man sich seine
eigene Funktion so:
============================================================
first:~/Programmierung/ocaml-versuche/styles oliver$ cat MyList.ml
(* --------------------------------------------------------------------- *)
let liste_1 = [1;2;4]
let liste_2 = [10;20;40]
(* Funktionsparameter-Reihenfolge ändern *)
let my_listiter2 li1 li2 func = List.iter2 func li1 li2
let _ =
List.iter2 (fun a b -> Printf.printf "%d\n" (a + b)) liste_1 liste_2;
print_endline "----------";
my_listiter2 liste_1 liste_2 (fun a b -> Printf.printf "%d\n" (a + b))
(* --------------------------------------------------------------------- *)
first:~/Programmierung/ocaml-versuche/styles oliver$ ocaml MyList.ml
11
22
44
----------
11
22
44
first:~/Programmierung/ocaml-versuche/styles oliver$
============================================================
Ggf. eigenes Modul schreiben, dann nimmt man statt List.iter2
eben MyList.iter2.
So, where's the problem?
>
> Wiegesagt, sind nur Kleinigkeiten, aber eine einheitliche For/If-Syntax
Kleinmigkeiten kann man ja auch schnell beiseite räumen... :)
[...]
> > > Man fängt nämlich an, Funktionen zu verweden an Stellen, wo eigentlich
> > > gar keine nötig sind. Egal, ob man sie nun inline definiert oder nicht,
> > > ist das unnötig schwer lesbar, IMHO. In Python:
> > >
> > > for a,b in zip(liste1,liste2): print a+b
> > ^^^^^^^^^^\
> > \
> > eine Funktion, wo garkeine nötig ist?
>
> Da wird eine aufgerufen, nicht definiert. Hab ich ja oben nochmal
> erklärt.
Ach so.
Wie macht man das nochmal mit den Zwischenergebnissen?
so, wie oben?
Naja, jetzt komme ich nochmal mit etwas Code daher
(habe das mal für eine int-Liste gemacht. (Naja könnte
man ja List-of-Pairs oder so nehmen):
========================================================================
module Direct =
struct
let rec sum = function
[] -> 0
| hd::tl -> hd + sum tl
end
module Accu =
struct
let rec sum li accu = match li with
[] -> accu
| hd::tl -> sum tl (hd + accu)
end
module Continuation =
struct
let rec sum li cont = match li with
[] -> cont 0
| hd::tl -> sum tl (fun v -> cont (hd + v));;
end
let rec cps what li tail cont = match li with
[] -> cont tail
| hd::tl -> cps what tl tail (fun v -> cont (what hd v))
(* --------------------------------------------------------------- *)
let int_list = [12; 4; 5; 22; 70]
let printer_int = Printf.printf "%d\n"
let _ =
(* Ressourcen-Fresser *)
printer_int (Direct.sum int_list);
(* nun die Ressourcen-Schoner *)
printer_int (Accu.sum int_list 0);
Continuation.sum int_list printer_int;
cps ( + ) int_list 0 printer_int;
cps ( + ) int_list 0 (fun x -> printer_int (x*x));
cps ( * ) int_list 1 printer_int;
cps ( ^ ) ["Ein"; " "; "Beispiel" ; "-"; "String"; "!"] "" (fun s -> print_endline s);
cps ( fun a b -> printer_int (a+b);a+b ) int_list 0 (fun a -> print_string "result: ";printer_int a)
(* beachte bitte bei "cps", daß Du Deinen Funktionsaufruf am Schluß hast. *)
(* Das war Dir doch wichtig?! Erzeugt auch keine Liste zwischendrin. *)
(* Und schont Ressourcen, weil kein StackSpace gebraucht wird. :) *)
(* Im letzten Beipiel: auch da kann man selbstverständlich die Reihenfolge *)
(* der Argumente ändern, wenn man will.... (oder einfach untereinander statt*)
(* nebeneinander schreiben ;-) :) *)
========================================================================
Laufen lassen des Codes:
========================================================================
first:~/Programmierung/ocaml-versuche/styles oliver$ ocaml direct-accu-cps.ml
113
113
113
113
12769
369600
Ein Beispiel-String!
70
92
97
101
113
result: 113
first:~/Programmierung/ocaml-versuche/styles oliver$
========================================================================
Na, ist doch auch schnuckelig, oder? :)
Gruß,
Oliver
Mehr Informationen über die Mailingliste linux-l