[linux-l] Ocml vs. Java

Oliver Bandel oliver at first.in-berlin.de
Di Sep 20 18:23:57 CEST 2005


Moin, Ivan,


On Tue, Sep 20, 2005 at 05:35:13PM +0200, Ivan Villanueva wrote:
> Hallo Oliver, 
> ich kenne nur Java, aber ich interessiere mich für Spracheigenschaften.
> 
> On Tue, Sep 20, 2005 at 02:14:07AM +0200, Oliver Bandel wrote:
> [über Ocaml]
> > ...aber OK, kurz und knapp:
> >  - funktional
> Java auch mit Interfaces (ohne pointers) aber sehr "verbose"

Na, das wage ich doch sehr zu bezweifeln, daß Java funktionale Programmierung ermöglicht.

Kannst Du in Java Funktionen als Argumente und als Rückgabewerte haben?
Also Funktionen eine Funktion als Übergabeparameter geben?


Beispiel: gegeben sind zwei Listen und zwei Funktionen.
func_1 addiert zwei Integers,
func_2 multipliziert zwei Integers.

Ermittle Summe und Produkte der jew. korrespondierenden
Elemente der beiden Listen:


        Objective Caml version 3.08.0

# let func_1 a b = a * b;;
val func_1 : int -> int -> int = <fun>
# let func_2 a b = a + b;;
val func_2 : int -> int -> int = <fun>
# let liste = [2;5;66;2;3;45;2;1];;
val liste : int list = [2; 5; 66; 2; 3; 45; 2; 1]
# let liste_2 = [4;2;4;55;6;7;8;10];;
val liste_2 : int list = [4; 2; 4; 55; 6; 7; 8; 10]
# List.map2 func_1 liste liste_2;;
- : int list = [8; 10; 264; 110; 18; 315; 16; 10]
# List.map2 func_2 liste liste_2;;
- : int list = [6; 7; 70; 57; 9; 52; 10; 11]
# 


Man übergibt func_1 bzw. func_2 als Argument an List.map2,
so, wie man auch die beiden liste als Argumente übergibt.

Stichwort: Higher-Order-Functions.



> >  - imperativ
> >  - objekt-orientiert
> Java auch

klar.
OO ist ja sicherlich Java's Schwerpunkt.



> >  - mächtiges Modulsystem (mit Funktoren (Funktionen über Module :)) !)
> Was ist das ? Wofür ist es gut ?

Sauberes Aufteilen des Codes, Code-Reuse, ...

Es gibt nicht nur die einzelnen Compilation-Units, also getrennte
Files, sondern eine eigene OCaml-interne Modul-Sprache.

Module bestehen aus Structures (die Implementierung) und Signatures
(das Interface).

Jede Structure hat eine Default-Signature, die alle definierten
Values frei zugänglich macht. Mit einer gesonderten Signature kann
mann dann alles verbergen, was man nicht haben will.
Dabei kann man die Typen der einzelnen Values sichtbar lassen,
oder (abstract data type) auch den Typ nur abstrakt zugänglich
halten.

Man kann Modulen auch nachträglich Signaturen aufprägen.

Das macht es z.B. einfach, einer Implementierung mithilfe
mehrerer Signaturen nach aussen anders erscheinen zu lassen,
z.B. trennung von Admin- und User- Funktionen.
Admin kriegt alles notwendige, User-Interface blendet
bestimmte heikle Funktionen aus. Diese Values sind nach Aussen hin
nicht sichtbar, so als ob sie nicht definiert wurden.

Funktoren:
Man hat ein Modul mit allgemeiner Implementierung (z.B.
Balanced Tree). Man will dies auf einen speziellen Datentyp
hin spezialisieren.
Dann definiert man die speziellen Funktionen in einem eigenen
Modul, setzt den Funktor auf die beiden Module an und hat als
Ergebnis ein neues Modul!

Sozusagen ein Modul als Parameter eines anderen zur Erstellung eines
weiteren.

Extrem geniales Feature! :)






> >  - rigides Typsystem; type-inference, compile-time checked, polymorphic 
> >  - gut sortierte Bibliothek
> Java auch. Kann man mehr "compile-time checks" machen als Java macht ?

Java ist nicht so rigide bzgl. Typsystem.
Solangfe auch nur noch ein Cast möglich ist...

polymorphic: List.map als Beispiel kann man Funktioen und Listen
jedes beliebigen typs übergeben, solange die Funktion die man anwendet und
die Liste auf die man sie anwendet vom Typ her passen.

type-inference: OCaml erkennt den Typ alleine.



> >  - pattern matching (im Sinne von Haskell, nicht im Sinne von Perl)
> Ist es ähnlich als in Java ?

Kenne ich in java nicht.
Ist ähnlich wie in Haskell.

Spart einem if-else-Konstrukte und switch-case-mäßiges Zeugs.


>     if (symbol.matches("([a-z]|[A-Z]|[0-9]|&|,|\\.|-|_)+")==false) {

Nein.



Beipiel:

(* ----------------------------------------------------------------- *)
(* is_dir dir  liefert als Ergebnis:                                 *)
(*       wenn dir ein Verzeichnis ist  -> true                       *)
(*       wenn dir kein Verzeichnis ist -> false                      *)
(*       wenn Fehler auftritt          -> false (und Fehlermeldung)  *)
(* ----------------------------------------------------------------- *)
let is_dir name =
    try
      match (Unix.stat name).Unix.st_kind with
       | Unix.S_DIR -> true
       | _          -> false
    with
      _ -> ignore ( output_string stderr ( "ignoring:" ^ name ^ "\n" ) ); false






> >  - performanter Compiler
> >  - performantes Compilat (und trotzdem Garbage Collection)
> Besser als gcj ?


kenne ich nicht.
weiß ich nicht.




> >  - interaktives Toplevel (Interpreter-like)
> Es gibt auch so etwas für Java

Aha.
Schon mit dabei?



> >  - Bytecode-Compiler
> Java auch

ja, klar.


> >  - Native-Code-Compiler für sehr viele Plattformen
> Java für manche

ok.


> >  - Garbage Collector (und dennoch sauschnell)
> Schon mit Java verglichen ?

Nein. Kenne Java aus dessen Anfangszeiten, da war es grauselig.
Soll ja besser geworden sein (kein Wunder, einige der OCaml-
Entwickler bauen auch bei Java mit :))


> >  - keine Pointer, keine Casts
> Java hat auch keine Pointer, Casts sehr wenig seid Java 5

Jeder Cast ist einer zu viel.
Wenn es die Sprache erlaubt, ist es Mist.



> >  - array/string boundary checks
> Java auch

aha, hatte ich vermutet.


> >  - ocamllex/ocamlyacc
> javacc habe ich vor kurz eingesetzt. Ein Kinderspiel.

lex/yacc? javacc?

Wo ist da der Zusammenhang?



> >  - camlp4 ---> Syntax-Extensions
> Was ist das ? Wofür ist es gut ? Hat es Ähnlichkeiten mit Metadata (Annotations)
> in Java 5 ?

Embedded DSLs zum Beipiel.
oder Pascal-Syntax für OCaml, oder diverses anderes Zeugs.

Metadata kenne ich nicht.
Es gibt aber auch ein MetaOCaml.
Ist aber nicht bei der eigentlichen Distri dabei.




> >  - Debugger kann vorwärts und rückwärts arbeiten
> Keine Ahnung ob es das für Java gibt, aber bestimmt.

Glaube ich nicht.
Geht IMHO nur bei funktionalen Sprachen.
Kenne keine andere Sprache, die das bietet.
(Vielleicht kann Lisp das?)



> >  - einfache Einbindung von C-Code
> In Java wurde vereinfacht, aber ich weiß nicht wie einfach das ist mit z.B.
> gcj

kenne gcj nicht.


>  
> > ..äääh, hab' ich alles?
> 
> Ich nenne ein paar andere Sachen in Java, die mir besonders gefallen:
> - 1000 Tools, z.B. junit, ant, umlgraph
> - Wunderbare Dokumentation
> - Sehr viel open source code. Vor kurz habe ich sogar 3 Open Source Projekte
>   gefunden, die etwas in Propositionale Logik gemacht haben.
> - Sehr einfach zu lernen und lesen: mir ist es lieber zu schreiben:
>     name.charAt(5)
>     als Gerogryphen wie z.B.: $n{5}
> - Objektorientierte Programmierung + Entwurfsmustern ist sehr mächtig

Funktionale Programmierung macht die meisten OO-Design-Patterns platt.
Man muß zwar umdenken, aber hat dann das meiste im Nu schon in der Kiste
und kann die Design-Patterns Literatur ins Museum bringen. ;-)


> 
> > Compiler, der mir wegen der Typprüfung immer auf die Finger haut, ziemlich
> > nervig.
> > Aber mittlerweile will ich das nicht mehr missen!
> > Das hilft so oft, Fehler schon sehr früh ausfindig zu machen.
> > 
> > Und das ist eine absolute Arbeitserleichterung.
> > Verkürzt die Debugging-Zeiten radikal. :)
> 
> Ich stimme total zu für Java

Naja, jeder macht so seine Erfahrung.

Komisch, daß unter den OCaml-Leuten auch viele Ex-Java-Leute sind und
Ocaml nicht mehr missen wollen. :-)


Gruß,
   Oliver



Mehr Informationen über die Mailingliste linux-l