POV-Ray : Newsgroups : povray.off-topic : Ocaml Server Time
4 Sep 2024 13:21:48 EDT (-0400)
  Ocaml (Message 1 to 10 of 17)  
Goto Latest 10 Messages Next 7 Messages >>>
From: Invisible
Subject: Ocaml
Date: 5 Feb 2010 09:00:05
Message: <4b6c2465$1@news.povray.org>
So today I started learning (or at least familiarising myself with) 
Ocaml (Objective CAML). But this isn't going to well; I find myself 
continually screaming at the computer screen "YOU'RE DOING IT WRONG!"

If you don't care about why Ocaml is wrong and why Haskell is better, 
you can stop reading now.



As best as I can determine, Ocaml is some sort of hybrid of Java and 
Haskell. It's "mostly functional" and has syntax resembling Haskell, but 
it also has object-oriented features.

Personally I prefer the 100% pure approach of Haskell. But hey, maybe 
sometimes it's better to be pragmentic and go with a hybrid approach. It 
could be interesting to at least see how that works out, right?

I get the impression Ocaml is from academia too (just like Haskell), but 
it's designed especially with a focus on performance. This alone 
probably explains why it's strict (like C, Java, VB, C#, Pascal...) 
rather than lazy (like Haskell). Making Ocaml strict rules out all sorts 
of possibilities, and gives lower performance in some cases, but it 
makes performance *predictable*. And that's probably the Big Reason for 
this design choice. [It also makes several implementation details much 
simpler.]



Problems become apparent almost immediately. I had a look at the Great 
Language Shootout, where I found Ocaml getting royally OWNED by both C 
and C++, mainly because both of these used all four CPU cores, while 
Ocaml apparently can't. Ocaml supports multiple light-weight threads, 
but because the garbage collector isn't thread-safe, all Ocaml threads 
run in a single OS thread - i.e., on a single CPU core.

Haskell, of course, runs your threads on several cores, like you'd 
expect. (Unless you specifically ask it not to because you're trying to 
interface to external C libraries that use thread-local storage.)

Of course, even Haskell currently has a parallel but not concurrent GC, 
and in particular to perform a GC cycle you have to wait for all Haskell 
threads to stop. (They can only be stopped at certain points.) This can 
cause large program slowdowns, where one thread is in a tight loop and 
won't stop, and all the other threads are paused waiting to start a GC 
cycle.

But hey, all of this isn't really to do with *Haskell*, but rather with 
*implementation*. Specifically, I'm talking about GHC. Other 
implementations do exist. [Most of them don't support SMP *at all* 
though.] You could write another implementation, or fix GHC, and the 
above drawbacks would go away. I have no idea how many Ocaml 
implementations there are, but it seems plausible you could also make it 
to real multithreading too.



Then I started to look at the syntax. It's *mostly* identical to 
Haskell, but with a few differences. Most of the differences are just 
/different/. Haskell uses one symbol, Ocaml uses a different one. No big 
deal. But a few of them are quite nausiating.

In Haskell, I can write

   foo = 5

In Ocaml, you must write

   let foo = 5

Small bit of superfluous chatter there. Still, I guess it makes the 
syntax more consistent. Slightly. But then we get to the next 
abomination: In Haskell, I can say

   foo = bar foo

but in Ocaml, you must say

   let rec foo = bar foo

Yes, that's correct, you have to manually tell the compiler that you're 
making a recursive definition. WTF? What, it isn't trivial enough for 
the compiler to detect this all by itself? (You might try to argue that 
it prevents you writing recursive definitions when you didn't mean to, 
but this is *functional programming*! Recursion is ubiquitous!)



Another puzzling thing is that Ocaml appears to use a layout rule 
similar to Haskell [not that the tutorial I'm following bothered to 
point this out], and yet it still requires explicit semicolons anyway. 
(??) And there's a set of fairly complex rules for when you must and 
must not write them. (?!?)



Now in Haskell - or in fact any vaguely modern programming language - if 
I want to add two numbers together, I say

   x + y

BASIC had this, Pascal had this, C had this, Java had this, Smalltalk 
had this, and Haskell certainly has this. But not Ocaml, apparently. 
Here you must use "+" for adding integers, "+." for adding reals, and 
"+/" for adding arbitrary-precision integers. (And presumably some other 
symbol for rational numbers, complex numbers, vectors...)

This seems pretty much inexcusible to me. I'm sure there's a technical 
reason for why they did it this way, but it seems like a very basic 
thing to get wrong. Some languages have overloading, some languages have 
classes, and some languages just have interfaces, but all of them seem 
to manage to avoid this. As far as I can tell, the above makes it pretty 
much impossible to write code that works on more than one number type.

In a similar vein, in Haskell "7" is a number. Any type of number. It 
can be anything. But in Ocaml, "7" is an integer, "7." is a real, and I 
forget what the syntax for an arbitrary-precision integer is.



In Haskell, you can say "Set Integer" or "Set String" or "Tree Integer" 
or whatever. Apparently in Ocaml you have to say this backwards: 
"integer tree" and so forth. I haven't yet seen any higher-kinded type 
constructors, but it'll be interesting to see how that works!

Haskell uses the convention that type NAMES must begin with a capital 
letter, while type VARIABLE must begin with a lowercase letter. Ocaml 
uses the arguably superior convention that type variables start with an 
apostrophy. (I would have used a different symbol, but it's a reasonably 
design choice. Somebody recently pointed out that some Unicode alphabets 
have no concept of "uppercase" and "lowercase".)

Which reminds me - in Haskell, "Char" is a 32-bit Unicode character. 
Ocaml makes the mistake of using an 8-bit ASCII code. (But apparently 
there are libraries to "work around the problem".)

Haskell has a thing called "tuples". A tuple is a fixed-length, 
fixed-type collection. For example, you might write a parser function 
that takes a string and returns (say) an integer and the remainder of 
the string. To do that, you return a 2-tuple containing an integer and a 
string.

The literal value of such a tuple can be written as

   (5, "rest of string")

and its type is written as

   (Integer, String)

Ocaml has the same syntax for writing tuples, but the type signature becomes

   integer * string

which seems a rather perverse choice. I can see what they're getting it 
(a tuple type is a product type, whereas an enum is a sum type), but 
that's still rather far-out.

(Haskell also uses "[Integer]" for a list of integers, and "[3,5,7]" for 
a value of this type. In general, the type signatures mirror the value 
syntax - possibly to the point of being confusing. Personally, I've 
never been that fond of the list and tuple syntax. Sure, lists and 
tuples are common, but would it really kill you to write "Tuple2 True 5" 
instead of "(True, 5)"? It would be clearer...)

Also, Haskell's "()" type becomes "unit". Which is the name Haskell 
programmers use to refer to it, but hey. It's not entirely clear to me 
whether Ocaml lets values of type "unit" actually exist - and if so, 
what their syntax is.



Haskell has algebraic data types. Every Haskell type is nominally an 
ADT. (Although in the case of "Int32", it's an enumeration type with 
constructors named "0", "1", "2"...) All types follow the same uniform 
structure.

Ocaml, on the other hand, has "records" which are like "{field1=5, 
field2=true, field3="hi"}", and "variants" which are like Haskell ADTs. 
And they're apparently not the same thing. You can see this when you 
define one:

   type recordX = {field1 : int, field2 : string, field3 : stuff}

   type variantY = Thing of int * string * stuff | OtherThing of char * char

So "records" use named fields, but have only a single (unamed) 
constructor, while "variants" allow multiple constructors, but use a 
wierd syntax for defining the fields - a syntax resembling tuple types, 
actually. WTF?

(This quite apart from the parameter of a parameterised variant being 
written *before* the variant name, not after it. I wonder if you can 
have multiple parameters on a variant? I haven't seen any examples 
showing this. I also haven't seem any parameterised records, so I'm not 
sure if that's supported. I'm also not sure how it knows from looking at 
a record which type you mean...)



Haskell makes the rather illogical choice of using "--" as the start 
marker for a comment. (Great. So I can't use that as a name then!) But 
Ocaml uses the even stranger choice of "(* ... *)". Which means that you 
can't write "(*)" to mean the multiplication function, you must write "( 
* )" [with spaces] to prevent it parsing as a comment.

[Then again, Haskell has a glitch with the unary minus function...]

Also, Haskell uses "++" for string (and list) concatenation. But Ocaml 
inexplicably uses "^" instead. (Haskell uses both "^" and "**" to mean 
exponent - but one is with an integer exponent and the other is with an 
arbitrary exponent. No, I can never remember which is which.)



Things don't get any better when you start looking at the build process.

In Haskell, if I want to compile a multi-module program, I say

   ghc --make MyThing

GHC will then automatically build the entire dependency tree, detect 
what libraries you need, check what (if anything) needs to be 
(re)compiled, compile it, and link everything to give you MyThing.exe. 
Hell, if a module has changed, it'll recompile it, but then it takes a 
hash of the interface file. If the module's implementation has changed 
but its implementation has not, the module will be recompiled, but 
anything depending on it will not.

It can even spit out a makefile if you wish, automatically generated 
directly from the source code. But usually, you just DON'T NEED make at 
all. GHC does it all for you.

In Ocaml, things are not so easy. Apparently YOU have to manually 
determine the correct order in which to compile things, and issue all 
the commands in the right order. (Or just use make.) You even have to 
compile and seperately link things - and tell the compiler whether it's 
supposed to be compiling or linking, and manually tell it what libraries 
to include. *sigh*

It gets even better though. If you write a source file and compile it, 
*everything* inside is public. If you don't want that, you have to 
*manually* copy and paste the names of the public stuff into an 
"interface file", and you apparently have to manually write in the 
correct type signatures. (So much for "Ocaml does automatic type 
inference".) You then have to insure that this file is compiled at the 
right moment - i.e., after the corresponding source file is compiled, 
but before anything depending on it is compiled.

Again, in Haskell you just write a list at the top of the source file 
saying what things should be public. The compiler does the rest. Even if 
you're manually running the compiler stages for some reason, the right 
thing happens. The object file and interface description are generated 
automatically in a single pass, and dependencies won't compile until 
these exist.

It is *claimed* that you can compile Ocaml into a library that can then 
be linked into programs written in arbitrary other languages (C or 
whatever). If so, that would certainly seem like an advantage. OTOH, 
Haskell can supposedly do this too - it's just that it'll be a bloody 
huge library! (Because it will contain a copy of the entire Haskell RTS.)

Actually, the latest version of GHC supports [on Linux only] dynamic 
linking now, so a Haskell library can be dynamically loadable, and the 
RTS can be dynamically loadable, and any other libraries you're using 
can be dynamically loadable. So if your C program uses 5 Haskell 
libraries, you still only have to link one (dynamic) copy of the RTS 
[which is fairly big].



It seems everywhere I look, Ocaml does the same things that other 
languages have done, but does them wrong. The bits that are right are 
identical to existing languages. The bits that are new are almost all wrong.


Post a reply to this message

From: Invisible
Subject: Re: Ocaml
Date: 5 Feb 2010 10:13:50
Message: <4b6c35ae$1@news.povray.org>
Wait... you're kidding me.

In Haskell, you can write

   foo = some function of bar

   bar = some function of foo

But apparently in Ocaml, this produces a compile-time error, since when 
foo is defined, bar hasn't been defined yet. Apparently you have to write

   let rec foo = some function of bar
   and bar = some function of foo

In other words, YOU have to manually resolve all circular dependencies 
by hand.

WTF?

(I remind you, this is functional programming and recursive definitions 
are ubiquitous...)


Post a reply to this message

From: Invisible
Subject: Re: Ocaml
Date: 5 Feb 2010 10:23:35
Message: <4b6c37f7$1@news.povray.org>
Curried functions + optional arguments = oh dear. :-)


Post a reply to this message

From: nemesis
Subject: Re: Ocaml
Date: 5 Feb 2010 11:30:00
Message: <web.4b6c468376b225035b39e120@news.povray.org>
Invisible <voi### [at] devnull> wrote:
> If you don't care about why Ocaml is wrong and why Haskell is better,
> you can stop reading now.
>
>
>
> As best as I can determine, Ocaml is some sort of hybrid of Java and
> Haskell. It's "mostly functional" and has syntax resembling Haskell, but
> it also has object-oriented features.

I stopped reading right here (though will still read the rest).

Haskell is not better, just different.  And no, OCaml is not a hybrid of java
and haskell:  it's a pragmatic OO successor to ML, which is the oldest static
typed, polymorphic functional language still in use today.  Curried functions?
Hindley-Milner type system?  Yeah, all coming from ML.  You could say OCaml is
ML++. :)

Haskell is Junior, ML is Senior, capisce? ;)


Post a reply to this message

From: Invisible
Subject: Re: Ocaml
Date: 5 Feb 2010 11:40:53
Message: <4b6c4a15$1@news.povray.org>
nemesis wrote:

> Haskell is not better, just different.

Right. So the huge list of "Haskell does X automatically but Ocaml makes 
you do it by hand" doesn't count as "better", just "different"?

> Curried functions?
> Hindley-Milner type system?  Yeah, all coming from ML.  You could say OCaml is
> ML++. :)

It even has "ML" right there in the name.

> Haskell is Junior, ML is Senior, capisce? ;)

Well, I've never seen ML, so I couldn't say if it's better or worse. But 
Oaml seems to lack so many useful things...


Post a reply to this message

From: nemesis
Subject: Re: Ocaml
Date: 5 Feb 2010 12:45:00
Message: <web.4b6c590a76b225035b39e120@news.povray.org>
Invisible <voi### [at] devnull> wrote:
> Problems become apparent almost immediately. I had a look at the Great
> Language Shootout, where I found Ocaml getting royally OWNED by both C
> and C++, mainly because both of these used all four CPU cores, while
> Ocaml apparently can't. Ocaml supports multiple light-weight threads,
> but because the garbage collector isn't thread-safe, all Ocaml threads
> run in a single OS thread - i.e., on a single CPU core.
>
> Haskell, of course, runs your threads on several cores, like you'd
> expect. (Unless you specifically ask it not to because you're trying to
> interface to external C libraries that use thread-local storage.)
>
> Of course, even Haskell currently has a parallel but not concurrent GC,
> and in particular to perform a GC cycle you have to wait for all Haskell
> threads to stop. (They can only be stopped at certain points.) This can
> cause large program slowdowns, where one thread is in a tight loop and
> won't stop, and all the other threads are paused waiting to start a GC
> cycle.

You're right.  The lack of concurrent GC is the single most important issue to
be fixed today, even Jon Harrop would tell that.  That's why you're seeing today
C and C++ beating OCaml real hard.  Because just a while ago -- when OpenCL,
OpenMP and other easily-parallelizing toolkits for C/C++ compilers weren't
generally available -- OCaml programs usually sported similar performance to
C/C++ and were also much clearer and shorter.

Eventually, it should get up to date.

> But hey, all of this isn't really to do with *Haskell*, but rather with
> *implementation*. Specifically, I'm talking about GHC. Other
> implementations do exist. [Most of them don't support SMP *at all*
> though.] You could write another implementation, or fix GHC, and the
> above drawbacks would go away.

yeah, but it's probably a very difficult issue.

> Then I started to look at the syntax. It's *mostly* identical to
> Haskell, but with a few differences.

Haskell is mostly identical to ML, which is OCaml's direct ancestor.  Miranda
the most direct ancestor to Haskell was based on ML's ideas.

> In Haskell, I can write
>
>    foo = 5
>
> In Ocaml, you must write
>
>    let foo = 5
>
> Small bit of superfluous chatter there. Still, I guess it makes the
> syntax more consistent. Slightly. But then we get to the next
> abomination: In Haskell, I can say
>
>    foo = bar foo
>
> but in Ocaml, you must say
>
>    let rec foo = bar foo

let and letrec are common constructs in Scheme as well.  They introduce scope
and recursively defined scope.

> Yes, that's correct, you have to manually tell the compiler that you're
> making a recursive definition. WTF? What, it isn't trivial enough for
> the compiler to detect this all by itself?

No, it's not trivial (oh such common word) at all.  Which is also why you don't
have many compilers for Haskell, but you get quite a good lot of good performant
compilers for both ML (Jersey ML, MLton, OCaml) and Scheme (Bigloo, Chez,
Gambit, Stalin etc).

> Another puzzling thing is that Ocaml appears to use a layout rule
> similar to Haskell [not that the tutorial I'm following bothered to
> point this out], and yet it still requires explicit semicolons anyway.
> (??) And there's a set of fairly complex rules for when you must and
> must not write them. (?!?)

I don't like all the semicolons either.  And the +. *. operators for
floats/doubles, but hey, at least these help on performance.

> In Haskell, you can say "Set Integer" or "Set String" or "Tree Integer"
> or whatever. Apparently in Ocaml you have to say this backwards:
> "integer tree" and so forth.

Being used to Pascal as well as C, I don't see the issue here.  It's just a
different way to state something:  "a set of integers" or "an integers set".

> Haskell uses the convention that type NAMES must begin with a capital
> letter, while type VARIABLE must begin with a lowercase letter. Ocaml
> uses the arguably superior convention that type variables start with an
> apostrophy.

I prefer Pascal and Scheme instance on the significance of names rather than
case.  (though the latest Scheme standard has gone to case-sensitive lameness)

> Which reminds me - in Haskell, "Char" is a 32-bit Unicode character.
> Ocaml makes the mistake of using an 8-bit ASCII code. (But apparently
> there are libraries to "work around the problem".)

It was not a mistake before Unicode showed up, it was common-sense, specially in
a performance-conscious programming environment.

> Haskell has algebraic data types. Every Haskell type is nominally an
> ADT. (Although in the case of "Int32", it's an enumeration type with
> constructors named "0", "1", "2"...) All types follow the same uniform
> structure.
>
> Ocaml, on the other hand, has "records" which are like "{field1=5,
> field2=true, field3="hi"}", and "variants" which are like Haskell ADTs.
> And they're apparently not the same thing. You can see this when you
> define one:
>
>    type recordX = {field1 : int, field2 : string, field3 : stuff}
>
>    type variantY = Thing of int * string * stuff | OtherThing of char * char
>
> So "records" use named fields, but have only a single (unamed)
> constructor, while "variants" allow multiple constructors, but use a
> wierd syntax for defining the fields - a syntax resembling tuple types,
> actually. WTF?

I don't know enough of OCaml to say this with 100% certainty, but I'd say it's a
design choice geared at, again, performance.  Just like C++ got plain structs
against the more heavyweight classes.

> Haskell makes the rather illogical choice of using "--" as the start
> marker for a comment. (Great. So I can't use that as a name then!) But
> Ocaml uses the even stranger choice of "(* ... *)". Which means that you
> can't write "(*)" to mean the multiplication function, you must write "(
> * )" [with spaces] to prevent it parsing as a comment.

Why would you write (*) 2 3 in OCaml when you can simple 2*3 or 2*.3?  (or even
in Haskell, except to make it look like Lisp ;)

(* this comes from Pascal and BTW,
 it spans several lines, which -- doesn't *)

Do you know what the Haskell multiline comment marker looks like?  I'll wait for
the answer.

> Also, Haskell uses "++" for string (and list) concatenation. But Ocaml
> inexplicably uses "^" instead. (Haskell uses both "^" and "**" to mean
> exponent - but one is with an integer exponent and the other is with an
> arbitrary exponent. No, I can never remember which is which.)

Different syntaxes coming from different language heritages.

> In Haskell, if I want to compile a multi-module program, I say
>
>    ghc --make MyThing

oh, you didn't get the fun times when GHC would compile down to C files and then
you ran the whole C-stack build process on your own, did you?  You missed half
the fun, my friend...

> In Ocaml, things are not so easy. Apparently YOU have to manually
> determine the correct order in which to compile things, and issue all
> the commands in the right order. (Or just use make.) You even have to
> compile and seperately link things - and tell the compiler whether it's
> supposed to be compiling or linking, and manually tell it what libraries
> to include. *sigh*

OCaml development is not as large or hip as Haskell's, so they have to make use
of whatever is ready for them, which means things like make.

> It gets even better though. If you write a source file and compile it,
> *everything* inside is public. If you don't want that, you have to
> *manually* copy and paste the names of the public stuff into an
> "interface file", and you apparently have to manually write in the
> correct type signatures. (So much for "Ocaml does automatic type
> inference".)

well, it does, but just as in Haskell, the H-M type system some times has to
sort out type ambiguities that may arise.  All but the simplest of modules don't
have type signatures.  The interface files just collect such signatures, which
is good because it's the only thing I have to go through instead of wading
through large source code just to lookup for signature or, worse, try to
understand from source code what the hell a function is expecting for parameter.

> You then have to insure that this file is compiled at the
> right moment - i.e., after the corresponding source file is compiled,
> but before anything depending on it is compiled.

That's why a Makefile is so useful. ;)

> Again, in Haskell you just write a list at the top of the source file
> saying what things should be public. The compiler does the rest. Even if
> you're manually running the compiler stages for some reason, the right
> thing happens. The object file and interface description are generated
> automatically in a single pass, and dependencies won't compile until
> these exist.

Good for Haskell that its large developers have recreated make inside it, but
not everyone can afford that.

> It is *claimed* that you can compile Ocaml into a library that can then
> be linked into programs written in arbitrary other languages (C or
> whatever).

It can, because source files are compiled into native object code.

> If so, that would certainly seem like an advantage. OTOH,
> Haskell can supposedly do this too - it's just that it'll be a bloody
> huge library! (Because it will contain a copy of the entire Haskell RTS.)

yes, pragmatism was the main force behind OCaml.


Post a reply to this message

From: Orchid XP v8
Subject: Re: Ocaml
Date: 5 Feb 2010 13:31:50
Message: <4b6c6416$1@news.povray.org>
>> Problems become apparent almost immediately. I had a look at the Great
>> Language Shootout, where I found Ocaml getting royally OWNED by both C
>> and C++, mainly because both of these used all four CPU cores, while
>> Ocaml apparently can't.
>>
>> Of course, even Haskell currently has a parallel but not concurrent GC,
> 
> You're right.  The lack of concurrent GC is the single most important issue to
> be fixed today, even Jon Harrop would tell that.  That's why you're seeing today
> C and C++ beating OCaml real hard.  Because just a while ago -- when OpenCL,
> OpenMP and other easily-parallelizing toolkits for C/C++ compilers weren't
> generally available -- OCaml programs usually sported similar performance to
> C/C++ and were also much clearer and shorter.
> 
> Eventually, it should get up to date.

I haven't checked yet, but I'm fairly sure the Shootout still has 
benchmarks for older, single-core systems. If I check that it should be 
informative.

>> But hey, all of this isn't really to do with *Haskell*, but rather with
>> *implementation*. Specifically, I'm talking about GHC. Other
>> implementations do exist. [Most of them don't support SMP *at all*
>> though.] You could write another implementation, or fix GHC, and the
>> above drawbacks would go away.
> 
> yeah, but it's probably a very difficult issue.

Well, as difficult as it is for any language, yes.

>> Yes, that's correct, you have to manually tell the compiler that you're
>> making a recursive definition. WTF? What, it isn't trivial enough for
>> the compiler to detect this all by itself?
> 
> No, it's not trivial (oh such common word) at all.

In exactly which way is it not trivial to determine that an identifier 
appears in the LHS expression?

> Which is also why you don't
> have many compilers for Haskell, but you get quite a good lot of good performant
> compilers for both ML (Jersey ML, MLton, OCaml) and Scheme (Bigloo, Chez,
> Gambit, Stalin etc).

Right. And but because nobody knows Haskell exists yet?

(Besides, there are half a dozen compilers out there. It's just that 
there's only one that's production-ready. Apparently there used to be more.)

> I don't like all the semicolons either.  And the +. *. operators for
> floats/doubles, but hey, at least these help on performance.

So does [or should] statically-known types. If you statically know that 
you're adding floats, replace + with +. and you're golden. It's not 
rocket science. (Actually it's program optimisation...)

It seems several design choices in Ocaml are specifically about making 
one special case faster at the expense of complexity and ugliness. Which 
is fine, I suppose, if you're just trying to win benchmarks rather than 
write maintainable software...

>> In Haskell, you can say "Set Integer" or "Set String" or "Tree Integer"
>> or whatever. Apparently in Ocaml you have to say this backwards:
>> "integer tree" and so forth.
> 
> Being used to Pascal as well as C, I don't see the issue here.  It's just a
> different way to state something:  "a set of integers" or "an integers set".

It's valid I guess, but I'm still curious to see what happens when you 
have multiple parameters...

>> Which reminds me - in Haskell, "Char" is a 32-bit Unicode character.
>> Ocaml makes the mistake of using an 8-bit ASCII code. (But apparently
>> there are libraries to "work around the problem".)
> 
> It was not a mistake before Unicode showed up, it was common-sense, specially in
> a performance-conscious programming environment.

I'll admit that not that many people use Unicode. Still, I imagine it 
means that if you try to adapt your program to work properly with 
Unicode, it breaks all over the place in unexpected ways.

> I don't know enough of OCaml to say this with 100% certainty, but I'd say it's a
> design choice geared at, again, performance.  Just like C++ got plain structs
> against the more heavyweight classes.

...except that C++ structs *are* classes. ;-)

Still, at least they didn't do that horrid C++ thing where you have to 
manually specify which methods you can override later.

>> Haskell makes the rather illogical choice of using "--" as the start
>> marker for a comment. (Great. So I can't use that as a name then!) But
>> Ocaml uses the even stranger choice of "(* ... *)". Which means that you
>> can't write "(*)" to mean the multiplication function, you must write "(
>> * )" [with spaces] to prevent it parsing as a comment.
> 
> Why would you write (*) 2 3 in OCaml when you can simple 2*3 or 2*.3?  (or even
> in Haskell, except to make it look like Lisp ;)

You wouldn't. But if you want to pass "*" to a high-order function...

> (* this comes from Pascal and BTW,
>  it spans several lines, which -- doesn't *)
> 
> Do you know what the Haskell multiline comment marker looks like?  I'll wait for
> the answer.

It's {- ... -}, which is vaguely more logical.

>> In Haskell, if I want to compile a multi-module program, I say
>>
>>    ghc --make MyThing
> 
> oh, you didn't get the fun times when GHC would compile down to C files and then
> you ran the whole C-stack build process on your own, did you?  You missed half
> the fun, my friend...

Current versions of GHC default to using the native code generator 
rather than GCC anyway. ;-)

>> In Ocaml, things are not so easy. Apparently YOU have to manually
>> determine the correct order in which to compile things, and issue all
>> the commands in the right order. (Or just use make.)
> 
> OCaml development is not as large or hip as Haskell's, so they have to make use
> of whatever is ready for them, which means things like make.

In which universe is Haskell "hip"? o_O

Well anyway, I thought Ocaml was far better known than Haskell, but I 
guess I could be wrong on that. It's just frastrating that they've 
designed the system in such a way that even if you were prepaired to 
write the code, it's not easy to automate.

> That's why a Makefile is so useful. ;)

Sure. But make doesn't determine dependancies; you have to do this 
manually. And if you get it wrong, your program presumably just doesn't 
link, or crashes when run. Kind of negates all the correctness benefits 
of functional programming...

>> Again, in Haskell you just write a list at the top of the source file
>> saying what things should be public. The compiler does the rest.
> 
> Good for Haskell that its large developers have recreated make inside it, but
> not everyone can afford that.

I repeat, make does not determine dependencies, it just decides what to 
do based on them. (Which is admittedly non-trivial in itself.) As far as 
I'm aware, there is no tool that writes makefiles for you. So GHC does 
far, far more than make. (In fact, there's an option to have it write a 
makefile for you, if you wish for some reason...)

>> It is *claimed* that you can compile Ocaml into a library that can then
>> be linked into programs written in arbitrary other languages (C or
>> whatever).
> 
> It can, because source files are compiled into native object code.

Doesn't necessarily mean you can link to it from the outside. (I'm not 
debating that you can, I'm just saying your explanation is incomplete.)

>> If so, that would certainly seem like an advantage. OTOH,
>> Haskell can supposedly do this too - it's just that it'll be a bloody
>> huge library! (Because it will contain a copy of the entire Haskell RTS.)
> 
> yes, pragmatism was the main force behind OCaml.

Presumably native object code from Ocaml must also contain the Ocaml 
runtime system too. (Including the GC, at least...)

Being pragmatic is fine - isn't that what made C so popular in spite of 
being rubbish? But it seems to be that there are a lot of poor design 
choices here that don't enhance performance in any way, they just make 
programming harder. Which is somewhat dissapointing.

I'm not saying Ocaml is completely rubbish. It does seem to have a small 
few interesting ideas in it. (The tutorial I read doesn't really explore 
these very much...) I just hope I never have to actually use it. :-}

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Darren New
Subject: Re: Ocaml
Date: 5 Feb 2010 14:54:52
Message: <4b6c778c$1@news.povray.org>
Invisible wrote:
>   integer * string
> which seems a rather perverse choice. 

Cartesian product of integers and strings.  I'm not sure what a "sum type" 
would be.

> instead of "(True, 5)"? It would be clearer...)

Wait till you get to python, where the tuple constructor is actually the 
comma, the parens are optional, and you try to figure out how to write a 
one-element tuple literal, or the empty tuple.

> Haskell makes the rather illogical choice of using "--" as the start 
> marker for a comment. 

Common in a lot of other languages like SQL and Ada. FWIW.

> Ocaml uses the even stranger choice of "(* ... *)". 

Which is Pascal for comments, if your keyboard (punched cards) don't have 
curly braces. FWIW.

-- 
Darren New, San Diego CA, USA (PST)
   Forget "focus follows mouse." When do
   I get "focus follows gaze"?


Post a reply to this message

From: Orchid XP v8
Subject: Re: Ocaml
Date: 5 Feb 2010 16:35:48
Message: <4b6c8f34$1@news.povray.org>
>>   integer * string
>> which seems a rather perverse choice. 
> 
> Cartesian product of integers and strings.  I'm not sure what a "sum 
> type" would be.

Either Int String

is a sum type. The set of possible values is the *sum of* the set of 
possible Int values and the set of possible String values.

Whereas... well, you understand what a Cartesian product is already, right?

Haskell's "algebraic data types" are sum types of product types. (The 
sum may contain only one summand, but a sum none the less. Actually, if 
you enable the EmptyDataDecls extension, zero summands are permissible...)

>> instead of "(True, 5)"? It would be clearer...)
> 
> Wait till you get to python, where the tuple constructor is actually the 
> comma, the parens are optional, and you try to figure out how to write a 
> one-element tuple literal, or the empty tuple.

Oh, the *type constructor* for a 2-tuple is "(,)", and for a 3-tuple 
it's "(,,)".

So if you want to be 73% anal, you can write "(,) String Integer" 
instead of "(String,Integer)". :-}

Off the top of my head, I don't *believe* this works with value 
constructors... No, wait. I'm wrong; it does work.

   (,,) :: a -> b -> c -> (a,b,c)

This means we can write

   zip = zipWith (,)

Eat THAT and smoke it! o_O

(Similarly, "[Char]" can also be written "[] Char".)

>> Haskell makes the rather illogical choice of using "--" as the start 
>> marker for a comment. 
> 
> Common in a lot of other languages like SQL and Ada. FWIW.

I know Eiffel uses it. But then, Eiffel is weird.

>> Ocaml uses the even stranger choice of "(* ... *)". 
> 
> Which is Pascal for comments, if your keyboard (punched cards) don't 
> have curly braces. FWIW.

...more useless information to add to my collection! o_O

Then again, in Pascal "(*)" is not a meaningful thing to write in the 
first place. ;-)

PS. I'm loving the way Haskell uses curly brackets for explicit 
grouping, AND ALSO for named-field syntax. Way to use the exact same 
symbol for two unrelated things that you might want to do AT THE SAME TIME!

-- 
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*


Post a reply to this message

From: Darren New
Subject: Re: Ocaml
Date: 5 Feb 2010 17:21:06
Message: <4b6c99d2$1@news.povray.org>
Orchid XP v8 wrote:
> Either Int String

Obvious once stated.

> Oh, the *type constructor* for a 2-tuple is "(,)", and for a 3-tuple 
> it's "(,,)".

Not in Python. The cosntructor for a 2-tuple is ,
No parens needed. Figure *that* one out. :-)

>> Common in a lot of other languages like SQL and Ada. FWIW.
> I know Eiffel uses it. But then, Eiffel is weird.

That too. All the "readable" languages tend to use it, because it's how you 
offset comments in English -- that is, if you have a comment to make.

-- 
Darren New, San Diego CA, USA (PST)
   Forget "focus follows mouse." When do
   I get "focus follows gaze"?


Post a reply to this message

Goto Latest 10 Messages Next 7 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.