[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