Ruby and Ocaml - my two favorite languages

While being away from Ruby land, I did investigate the OCaml language
further.

I’ve earlier posted some information on OCaml in this group when I was just
starting to look at the OCaml language. This is a follow up after I have
gaining more experience.

I can now confidently say that Ruby and OCaml are at the absolute top of
programming languages. I’m a bit annoyed with the fact the OCaml is in fact
so good the it steals ground from Ruby. Its a bit like a Japanese
sportsmotorcycle compared to a European ditto with the nationalities
reversed.

OCaml with static linking with C object files is better suited for large
system applications than Ruby both becuase its faster and due to
distribution of runtime as exe rather than clear source files. What really
surprised me was that OCaml actually competeded with Ruby in the discipline
of rapid prototyping and still managed to produce better code than carefully
developed C++ code requiring significantly more development time.

Still many bright things are happening for Ruby and I am certainly not going
to dismiss Ruby.
I’m looking forward to see Ruby increasingly involved in building the future
Web both via integration with Apache and the support of Web Services where
Google have been kind enough to be a Ruby front runner. And this is possible
the best recognition you can get, because I can’t think of a greater
application the Google.

Ruby on the other hand is class example in OO development, but what is
really great OO or not, is that you can actually write modules of 2K size
that does meaningful things and plugs seamlessly into the development
environment.
Ruby initially impressed me with huge number of highly functional but
redicously small library implementations in native Ruby. I spend hours
searching for what the rest of the a database interface because it couldn’t
possibly all be in those 2.5 K.

You can also write suprisingly short programs in OCaml, but overall there is
more fuzz with getting the source file dependencies right in the makefile
which also complicates integrating third party tools not in the standard
distribution.

While Ruby is a language with one of the easiest FFI’s (foreign function
interface), it is actually easier in OCaml. In fact it is so easy that
provided you stick to certain datatypes, it can be almost be neglected
whether you write a function in C or OCaml: Instead of writing a C prototype
in a .h file, you write a similar line in OCaml and use it as if it was a
native OCaml function. Accesing OCaml in the C function requires a macro on
the argument to get the desired C type, not unlike Ruby. Callbacks the other
way around is also quite managable although not as trivial. I once looked at
an enormously complex JNI interface, only to discover that this was the new
greatly simplified JNI interface… go figure.

The OCaml syntax is not the best I’ve seen, so I tried to imagine all kinds
of improvements. However, once I got used to it, I still didn’t quite fancy
it, but I was hard pressed coming up with anything better that would be
equally efficient. OCaml is as terse as is possible without becoming
entirely unreadable. I think you could actually mix some of Ruby’s syntax
with OCamls functional concepts and get an even greater language. Must do so
one day :slight_smile:

It appears that you actually write shorter programs in OCaml than in Ruby,
however, you also maintain separate interface files for larger programs.

I wrote a Ruby hack to convert Yacc grammar file into a Visual Parse ditto.
This included lineparsing and grabbing a name, making it upper case and add
a counter for each alternative of the rule. Ruby is a natural for these
tasks. I started out doing a manual conversion, but halfway down realized it
was actually worthwhile to write a Rubyscript just to complete the other
half. And it actually was faster to write the Ruby program than the manual
conversion I did on the first half of the file.

Later I tried to write the same conversion in OCaml both to see how it would
work out, and also because I could then have an executable that did not
require Ruby to be installed. I turned out to be equally easy to write the
program in OCaml. Result was possibly slightly shorter. Execution time was
irrelevant but instant in both cases. The write code then run a test cycle
was very fast in both languages. OCaml has a toplevel interpreter that makes
it possible to execute code much like Ruby - but it still needs to link
libraries. For that purpose OCaml has a program that generates a new
toplevel interpreter linked with the libraries you specify. Once a new
toplevel with the necessary string library was created, the development
phase compared to Ruby. OCaml requires very frequent tests because it is
strongly type checked. Like Ruby you do not actually write the type because
it can figure it out. However, you do not want to write a bunch of code and
then figure out what you did wrong with a host of infered types being
something you cannot guess what is. Upside is that with early test this
works well and it did help me avoid some tricky bugs I made in the Ruby
version.

The slightly disappointing side of this is, from a Ruby perspective, is that
OCaml seems to be strong also in those areas where Ruby were supposed to be
uniquely strong. Still Ruby is the more natural, elegant and accessible
language.

Ruby has embedded regular expressions which is something OCaml does not have
directly but through a regex type. Next version of OCaml will include a
preprocessor extension that will directly inject regular expressions into
the language core, without doing anything to the core language. This change
will also make it possible to create entire lexers directly in the language.
The OCaml preprocessor is far from trivial to work with, but you can do some
amazing things with it.

While OCaml do have support for Objects and it does have some kind of
polymorphism, this is clearly an area where Ruby is better off thanks to the
dynamic typing. The price in Ruby is that you need more runtype type
checks - which is something you’d have to remember to do in order to avoid
runtime errors. But in the end you have to cover all possibilities somehow
in either language.

If I could I’d use Ruby as a scripting language for application automation
language and develop large applications in OCaml. With these two tools,
there is only low-level C programming left and little space left for C++
development. I can positively say that for certain types of applications
OCaml is 5 to 10 times faster to implement than C++ (for an experienced C++
developer and inexperienced OCaml developer) because I did prototype in
OCaml and subsequently implemented in C++. I’ve no reason to believe this is
different for Ruby, except Ruby doesn’t link into executables which kind of
disqualified it for the purpose. Runtime wise I have no data, but I’m sure
the runtime is faster in OCaml than C++ due to reduced ability to retain
strong typing in C++ without using rather complex template programming. I
believe Ruby runtime would not have been significantly slower for the same
reason. Ruby deals with dynamic typing and handles memory management. Why is
it so much faster to write code in Ruby or OCaml? Fewer steps from concept
to implementation means less work resulting and fewer errors and faster
results increases motivation to see yet more results rather than falling
asleep over the debugger.

While I do envy the garbage collection of Java and C#, and possibly the
libraries, I still consider C++ a much more powerfull language but also much
more difficult and unnecessarily complex. You can then extrapolite this with
what what I wrote above. Obviously a global standard such as Java is worth
much, but the courage to go you own way has a value of its own. I do not
agree with all the Paul Graham writes, but after all it was in the NG I was
introduced to his article Beating the Averages.
http://www.paulgraham.com/avg.html
Which somehow makes me think of beating the top dog…

[after writing the above, I found the following article at Grahams site for
his new arc language:
http://www.paulgraham.com/vanlfsp.html it mentions OCaml as a langauge for
smart people and Java for the masses - your free to add Ruby to LFSM]

In conclusion: obviously there are many and many good languages around and
you can’t say a language is the best for all purposes. But I’ve been
searching for a successor to C++ and came up with two languages worth
further investigation. So since you already know Ruby, I’d recommend you
also take a look at OCaml.
The very great and huge book developing applications with OCaml was recently
published in a preview english translation online:
http://www.ocaml.org/
http://caml.inria.fr/oreilly-book/

I feel it has been a long journey to find a new useful language, and I feel
compelled to to repeat Doug Baglays editorial because I tend to agree. Both
Ruby and OCaml gets good mention
http://www.bagley.org/~doug/shootout/editorial.shtml

But while Ruby and OCaml may be my favorite languages, it is only because C
for all its quirks has lifted itself out of the ordinary and become the
atmosphere that makes programming possible.

Finally, Ruby cannot too soon get better closure integration as first class
values and partial evaluation support. This is an absolute killer feature of
OCaml. Most of what Ruby does great is thanks to its use of closures and
most of what Ocaml does better is thanks to its improved use of closures.

Mikkel

Finally, Ruby cannot too soon get better closure
integration as first class values and partial evaluation
support. This is an absolute killer feature of
OCaml. Most of what Ruby does great is thanks to its use
of closures and most of what Ocaml does better is thanks
to its improved use of closures.

I’m curious. Could you give an example of this?

···


– Jim Weirich jweirich@one.net http://w3.one.net/~jweirich

“Beware of bugs in the above code; I have only proved it correct,
not tried it.” – Donald Knuth (in a memo to Peter van Emde Boas)

Of course, there’s no reason why you couldn’t use GC with C++; there
are some good libraries for this.

My feeling is that using C++ with GC and the STL (and C++ strings)
would result in considerably fewer C style bugs (stray pointers,
buffer overflows, multiple frees, etc.) and faster development.

···

On Tuesday 30 July 2002 05:57 pm, MikkelFJ wrote:

While I do envy the garbage collection of Java and C#, and possibly
the libraries, I still consider C++ a much more powerfull language
but also much more difficult and unnecessarily complex.


Ned Konz
http://bike-nomad.com
GPG key ID: BEEA7EFE

“Jim Weirich” jweirich@one.net wrote in message
news:87y9bsd7fb.fsf@traken.access.one.net

> Finally, Ruby cannot too soon get better closure
> integration as first class values and partial evaluation
> support. This is an absolute killer feature of
> OCaml. Most of what Ruby does great is thanks to its use
> of closures and most of what Ocaml does better is thanks
> to its improved use of closures.

I’m curious. Could you give an example of this?

In the past year there have been some threads on this topic and some
examples of how this can be accoplished in Ruby search for “Ruby partial
evaluation” in Google groups.

I should remind that I’ve been of the group for a while and there may be
have been issues with the closure syntax since then.

An example of an anonymous closure stored in a variable:
def dosomething (x y)
x(y)
end

sqr = {|a| a*a}
puts sqr(2) # => 4
puts dosomething(sqr, 3) # ==> 9

You can do this now, but it involves writing somewhat more.
Notice both that a function, or closure, can be stored in a variable and be
passed around to other functions.
It can be evaluated by putting parentheses on it.
The next step is partial evaluation, and for this to work, it is essential
that you can store a closure in a variable.
A closure is a microclass: it has some data and some code. The normal
closure is just a pointer to some code.
With partial evaulation, the closure also stores the value of some of the
parameters (and sometimes also parts
of the environment).

Let’s partially evaulate a sum function:

sum = {|a,b| a + b}
add3 = sum(3)
puts add3(2) #==> 5

Another kind of partial evaluation that would be insanely cool is where the
object parameter is partially evaulated. This means that you can pass around
a member function. Since all functions in Ruby are member functions, this is
actually necessary in order to have function pointers, or delegates (the
infamous fight between Microsoft and Sun).
class X
def initialize
@name = "rock"
end
def identify()
puts @name
end
def rename(s)
@name = s
end
end

Notice in the following that when no parentheses is used, the function is
not evaluated, its closure
becomes the value. This is not standard Ruby and a future Ruby syntax would
probably need to
invent something else.

a = new X
b = a.y
b() #=> rock
a.rename(“flower”)
b() #=> “flower”

Mikkel

Agreed. Many people go searching for a new language instead of using
the provided libraries for a language. That’s a good reason to use
C, scheme, and C++, too. Just because you can do regexp’s in Perl,
and not easily in C++ (without a library) doesn’t mean you should
switch to perl just because it offers regexps. I think that’s really
ridiculous.

On the other hand ruby overall offers a somewhat more pleasant
experience to the programmer, given that it doesn’t try to be
downwards compatible to C, and thus is more high level :slight_smile:

(still, I want lisp style macros in ruby … gotta forge my own, eh? :slight_smile:

-Martin

···

On Thu, Aug 01, 2002 at 01:17:35AM +0900, Ned Konz wrote:

On Tuesday 30 July 2002 05:57 pm, MikkelFJ wrote:

While I do envy the garbage collection of Java and C#, and possibly
the libraries, I still consider C++ a much more powerfull language
but also much more difficult and unnecessarily complex.

Of course, there’s no reason why you couldn’t use GC with C++; there
are some good libraries for this.

My feeling is that using C++ with GC and the STL (and C++ strings)
would result in considerably fewer C style bugs (stray pointers,
buffer overflows, multiple frees, etc.) and faster development.

“Ned Konz” ned@bike-nomad.com wrote in message
news:200207310916.58062@ned.bike-nomad.com

Of course, there’s no reason why you couldn’t use GC with C++; there
are some good libraries for this.

My feeling is that using C++ with GC and the STL (and C++ strings)
would result in considerably fewer C style bugs (stray pointers,
buffer overflows, multiple frees, etc.) and faster development.

Actually STL greatly reduces the need for GC thanks to its built in memory
management. Still GC offers a lot of extra opportunities for cleaner designs
and safer development.
Although there are GC for C++, I don’t consider them a serious option for
normal development. For special purposes such as handling message buffers
for SOAP interfaces, GC has been successfully used.

There are also C-like languages that deals with some of these issues - I
believe one interesting variant is called Vault (as I recall). It’s more
inference based deallocation. A new langauge with C-level control and better
memory management would be great.

Even with GC in C++, there are efficient languages with native GC, so why
not use them?

Mikkel

class X
def initialize
@name = "rock"
end
def identify()
puts @name
end
def rename(s)
@name = s
end
end

Notice in the following that when no parentheses is used, the function is
not evaluated, its closure
becomes the value. This is not standard Ruby and a future Ruby syntax would
probably need to
invent something else.

a = new X
b = a.y

Shouldn’t this read “b=a.identify”? Just to be sure I understand this
closure thingy right.

b() #=> rock
a.rename(“flower”)
b() #=> “flower”

-billy.

···

On Wed, Jul 31, 2002 at 10:57:32AM +0900, MikkelFJ wrote:


Meisterbohne Söflinger Straße 100 Tel: +49-731-399 499-0
eLösungen 89077 Ulm Fax: +49-731-399 499-9

My feeling is that using C++ with GC and the STL (and C++ strings)
would result in considerably fewer C style bugs (stray pointers,
buffer overflows, multiple frees, etc.) and faster development.

Agreed. Many people go searching for a new language instead of using
the provided libraries for a language. That’s a good reason to use
C, scheme, and C++, too. Just because you can do regexp’s in Perl,
and not easily in C++ (without a library) doesn’t mean you should
switch to perl just because it offers regexps. I think that’s really
ridiculous.

Good point, but C++ and Perl can’t be reasonably considered to occupy the
same “space”. If you can do your huge system in C++ and parse the text
inputs and outputs with Perl, for instance, that would be reasonable.

On the other hand ruby overall offers a somewhat more pleasant
experience to the programmer, given that it doesn’t try to be
downwards compatible to C, and thus is more high level :slight_smile:

Agreed.

(still, I want lisp style macros in ruby … gotta forge my own, eh? :slight_smile:

-Martin

–Gavin

···

----- Original Message -----
From: “Martin Weber” Ephaeton@gmx.net

“Philipp Meier” meier@meisterbohne.de wrote in message
news:20020731091242.GM3140@o-matic.net
a = new X

b = a.y

Shouldn’t this read “b=a.identify”? Just to be sure I understand this
closure thingy right.

b() #=> rock
a.rename(“flower”)
b() #=> “flower”

Certainly, I renamed y to identify, but failed to do so everywhere.

Mikkel