View Full Version : OCaml
Zoldar256
2003.08.25, 08:58 PM
I have always loved ML. And have used SML-NJ quite a lot. But i never considered it as a replacement for the tried and true C++. But then I found Ocaml. A ML derivative, compiles to native code with great performance (People generally claim performance is faster to no more than 10% slower than equivalent C code), and has objects too. Plus it can interface with C code easily enough if needed.
Now I'm real tempted to drop C++ (Except for when I really really can't get by without it) and do my game/engine coding in Ocaml.
Anybody have experience with OCaml? I haven't tried making any games with ML, or any app over 600 lines (Which is a lot in a functional language) so I'm curious what results anybody has had for games.
codemattic
2003.08.26, 07:17 AM
all of Abuse's scripting was written with Lisp. Abuse is now opensource (and there is a OS X version) so you can look at the code.
<http://www.labyrinth.net.au/~trandor/abuse/>
if you download just the app - you can "show package contents" from finder and you can look through the lisp folder to see the code.
codemattic
2003.08.26, 02:02 PM
Zoldar256 -
sorry - when I saw ML I thought you were talking about a variant of Lisp - Ive never heard of Meta Language before. Sorry for veering off-topic.
Zoldar256
2003.08.26, 02:20 PM
hehe. No problem.
That is interesting though. Kinda surprised Lisp was used, but it looks like Lisp worked great for the job.
OneSadCookie
2003.08.26, 04:46 PM
Whilst we're sort of on the subject, Jak and Daxter was mostly written in a LISP variant...
codemattic
2003.08.26, 09:29 PM
Originally posted by OneSadCookie
Whilst we're sort of on the subject, Jak and Daxter was mostly written in a LISP variant...
yes! They talk about it in their postmortem <http://www.gamasutra.com/features/20020710/white_pfv.htm> (free-registration required). Its an interesting read on pros and cons of using your own scripting language.
"5. GOAL rules! Practically all of the run-time code (approximately half a million lines of source code) was written in GOAL (Game Object Assembly Lisp), Naughty Dog's own internally developed language, which was based on the Lisp programming language. Before you dismiss us as crazy, consider the many advantages of having a custom compiler."
... and then later ...
"What Went Wrong
1. GOAL sucks! While it's true that GOAL gave us many advantages, GOAL caused us a lot of grief." ...
But anyway - you can always write your engine in C/C++ and use whatever scripting/functional/interpreted/whatever language for the game logic. Whatever you feel like you can code the fastest and cleanest in.
codemattic
2003.08.26, 09:33 PM
could you explain what you like about functional programming? Ive read a bit on Haskel, but was unable to grok what the advantage is.
cheers
Quicksilver
2003.08.27, 12:50 AM
Originally posted by codemattic
Ive read a bit on Haskel, but was unable to grok what the advantage is.
I see someone has read a certain good book :cool:
Zoldar256
2003.08.27, 01:24 AM
There are several things I like about functional languages and more specifically ML.
The biggest is I find most algorithms can be expressed more naturally in a functional language. Especially those that involve some kind of recursive structure like binary trees. This generally results in significantly less code you have to write.
For instance adding one to each element in a list:
Functional:
addOne [] = []
head :: tail = head + 1 :: addOne tail
Procedural (C++):
void addOne(std::vector<int>& array)
{
for(std::vector<int>::iterator i = array.begin();
i != array.end();
++i)
*i = *i + 1;
}
You can imagine if your intent was to add any given value to a each element of a tree. The procedural one would get significantly more complicated, but the functional one (At least in ML with recursive data types) would only be 2 or 3 lines longer.
Another interesting feature is that functions are first class variables. Just like ints and floats. This is closely related to the concept of a closure. A closure is loosely defined as "The function that results from applying a given environment to a function". This closeure can be assigned to a variable and results in a new function.
Back to the adding to the list example:
let rec addToList num lst =
match lst with
[] -> []
| head :: tail -> (head + num) :: addToList num tail;;
let addOne = addToList 1;;
Now addOne is the function that represents what addToList will do when given 1 as the first argument and whatever addOne is given as the second argument.
This presents a different, albeit less obvious way of doing object oriented programming.
Which can be a problem since I have been trained for software design using a Java or C++ style language. Objects Objects Objects. Closures is not tossed around in software design very often.
ML is also strongly typed. All variables are type checked at compile time. Kinda the philosophy of: If the types are guaranteed to be correct then the code is correct and won't crash. Less debugging time, more strict compilers.
Some things don't apply well to recursive style programming however. Like threads, and simple for loops. Objects are also tricky business with closures flying about and strong type checking.
Anyways, I have just come to the conclusion that I should just try it out. Best way to learn is through experience right?
(PS. All of this was written very quickly... So I might be wrong on some of the fine points.)
OneSadCookie
2003.08.27, 03:13 AM
Just to point out that closures aren't restricted to functional languages. Plenty of procedural scripting languages (for example Ruby) support them.
I think most of the other points were subjective, though there are definitely benefits to a type system which guarantees you'll never segfault or bus-error :)
Zoldar256
2003.08.27, 05:19 AM
I didn't know Ruby had closures...
And of course it's all subjective. But I'm bored from too much C++ so I'll take any type of opinion ;-)
Originally posted by Zoldar256
For instance adding one to each element in a list:
Functional:
addOne [] = []
head :: tail = head + 1 :: addOne tail
Procedural (C++):
void addOne(std::vector<int>& array)
{
for(std::vector<int>::iterator i = array.begin();
i != array.end();
++i)
*i = *i + 1;
}
If you only only want to count lines of code, I can do that in one line in C++:
transform(array.begin(), array.end(), array.begin(), bind2nd(plus<int>(), 1));
:D
Seriously though, this isn't a lines-of-code contest. My experience with functional languages is minimal at best (very basic experimentation with Haskell), but I can see many advantages. As a "math" guy the declarative nature of functional languages really appeals to me. I'd love to implement some real-world problem in a functional language to see for myself the advantages/disadvantages over C++ (the procedural language I work in most often), but I don't think I can convince the guys at work to go for that.
And here's why... when I think about it, very little of my time is spent defining algorithms, or even debugging algorithms. When I think about this, the benefits of a function language start to fade. How is a functional language going to help me interface with a SQL database better? How is it going to help me create a GUI? How is it going to help me parse text files better? These are the questions that keep me from even trying to justify using a functional language for tasks at work. I guess my programming tasks boil down to "can I access the libraries I need" more than "how clean, clear, and theoretically beautiful is the syntax of the language". And, for good or bad, the libraries follow the programming herds and the herds use C++.
I know I can probably call C/C++ code from most functional language, but my previous experience on cross-language apps tells me that passing any kind of semi-complicated data structure across the language boundary eats up a lot of programming and debugging time all by itself. Does this negate any advantage of going with the functional language in the first place? I guess, like Zoldar256, I'll just have to do some experimentation to find out.
Zoldar256
2003.08.27, 08:29 PM
hehe. Yes well, I really should avoid the "lines of code" argument. It has no real merit. But you got what I was going for. Some things just make more sense implemented functionally.
As for accessing external libraries. Making bindings has been a huge pain in the a** for a lot of non-C languages. Sometimes their niceties don't translate well into the low level. Luckily I haven't found to many issues with OCaml.
Ocaml can output standard C style object files. And there is only a few extra steps to call OCaml functions from C.
And here's why... when I think about it, very little of my time is spent defining algorithms, or even debugging algorithms. When I think about this, the benefits of a function language start to fade.
Interesting... I think all my time is defining interfaces, the underlying design and algorithms. All of these have changing design goals. So the ability to rapidly change the algorithm and experiment and how the various components of the software relate to eachother is essential in my opinion.
How is a functional language going to help me interface with a SQL database better? How is it going to help me create a GUI? How is it going to help me parse text files better?
I dunno about interfacing with a SQL database.. But create GUI's again have treelike structures for the hierarchy of elements, lists and other standard software design patterns. So really if the pattern applies well to a functional language it would help. I know many times while coding MVC style UI's I'd like to use closures to replace simple delegate classes.
While GUI's are questionable on which one is better. Parsing text files? Ah easy, functional. BNF or whatever your favorite grammar language is very reminiscent of a functional language. So I think parsing is much more natural with a functional language.
Though IMHO. Lex and Yacc have really made this a non-issue regardless of target programming language.
So really if the pattern applies well to a functional language it would help. I know many times while coding MVC style UI's I'd like to use closures to replace simple delegate classes.
In the various discussions of functional languages around on the net, "closures" often come up. Despite reading numerous definitions and examples, I'm still not sure I know what they are. Are they something more than idea of "first class" functions? In other words, functions that can be returned from other functions, passed as arguments to other functions, stored in variables, etc?
While GUI's are questionable on which one is better. Parsing text files? Ah easy, functional. BNF or whatever your favorite grammar language is very reminiscent of a functional language. So I think parsing is much more natural with a functional language.
Though IMHO. Lex and Yacc have really made this a non-issue regardless of target programming language.
I think I overstated my text file usage. "Parsing" is probably too strong a word. "File I/O" would have better described what I was trying to say, usually it just involves reading tables of data into data structures, processing the data structures, and outputting the processed data back to a file. Though, maybe, if I took the time to formalize it a bit more, I could get by with using more reusable code (like that created via Lex/Yacc) instead of starting from scratch for each new task. Something to keep in mind.
What I was really getting at though, is that it seems to me that the examples lying around for how great such-and-such functional language is usually involve things like calculating Fibonacci numbers, or factorials, or something where the concept is very well matched to a functional style. But this sort of core, "math-like" functionality is where I spend very little time of my programming/debugging time. Most of it is on interfacing with external libraries (database access, networking, etc) or some sort of user interaction (input files, GUI displays, etc.). If we're in a MVC world, functional languages seem to me to fit the model part, but not so much the controller part where I seem to spend most of my time.
Maybe I'm unusual in this way, but I don't think so. Admittedly if I were to read intros to C++ programming on the web with the same level of familiarity (or lack thereof) that I have with OCaml, I'd probably have the same complaint ("OK, great, I can output 'Hello world!', but how does that help me write a real program!?!?").
Anyway, this discussion has convinced me to try out OCaml (http://www.ocaml.org/). I'm downloading it right now (found an OS X how-to and installer here (http://caml.inria.fr/caml-macosx-howto/index.html), for anyone reading along at home). So you may have a convert on your hands. I can come to you with all my questions, right? :)
Zoldar256
2003.08.29, 01:54 AM
In the various discussions of functional languages around on the net, "closures" often come up. Despite reading numerous definitions and examples, I'm still not sure I know what they are. Are they something more than idea of "first class" functions? In other words, functions that can be returned from other functions, passed as arguments to other functions, stored in variables, etc?
A closure a function with the environment at the time of it's creation applied. An environment in this case is all the variables currently in scope and their values.
Using a bad example. Take this function
float power(float x,unsigned int y)
{
if(y == 0)
return 1.0;
return x*power(x, y-1);
}
the closure of applying the environment equivalent to assigning x the value of 4.0. IE, the first argument is 4.0. Is equivlent to:
float power4(unsigned int y)
{
if(y == 0)
return 1.0;
return 4.0*power4(y-1);
}
So I suppose closures are kinda like functions that represent the partial evaluation of another function.
Sorry about my bad explanation, hope you get the idea tho.
What I was really getting at though, is that it seems to me that the examples lying around for how great such-and-such functional language is usually involve things like calculating Fibonacci numbers, or factorials, or something where the concept is very well matched to a functional style.
Exactly why I started this thread. Aside from some very specific applications (Compilers, parsers theorom provers) I have seen very little "real-world" applications done in a functional language.
Ocaml taunted me however since a lot of the FAQ's seemed to claim that it was good for "real-world" applications. There's even a web browser written in OCaml. Some guy also wrote an OpenGL fps in Ocaml for a class. Not very real world. But I never saw anybody say, "Hey here's my FPS written in SML/Haskell/Rex!"
And that's what got me thinking.
If we're in a MVC world, functional languages seem to me to fit the model part, but not so much the controller part where I seem to spend most of my time.
Yea... they do only seem well applied to the model part.
After using Cocoa I can't imagine doing the controller&view in anything else anyways. :D
Anyway, this discussion has convinced me to try out OCaml. I'm downloading it right now (found an OS X how-to and installer here, for anyone reading along at home). So you may have a convert on your hands. I can come to you with all my questions, right?
:blink: :p
Uh oh.... hehe. I never said I was "good" at OCaml :D
But I'd love to hear how it goes!
Note: OCaml can also be installed using Fink.
OneSadCookie
2003.08.29, 05:17 AM
Originally posted by Zoldar256
But I never saw anybody say, "Hey here's my FPS written in SML/Haskell/Rex!"
Quake Haskell?
(Quite possibly the worst example of functional programming ever, but hey!)
Originally posted by Zoldar256
So I suppose closures are kinda like functions that represent the partial evaluation of another function.
Sorry about my bad explanation, hope you get the idea tho.
That does help a lot, thanks. With this thread and this online book (http://caml.inria.fr/oreilly-book/html/index.html), it's all starting to come together. Any idea why they are called "closures"?
Zoldar256
2003.08.29, 02:25 PM
Free Orielly books.... Mmmmmmmmmmmmmmmmmmmm
Any idea why they are called "closures"?
I have no idea. I'll check a book on programming language theory as soon as I get back from vacation.
Only relation I can think of is: "Closing" something, like a transaction, usually means completing it from some partially completed state. So thus a Closure is what completes a partially completed function?
codemattic
2003.08.29, 07:32 PM
Originally posted by M.J.
If we're in a MVC world, functional languages seem to me to fit the model part, but not so much the controller part where I seem to spend most of my time.
Interesting. I think we all spend too much time writing our controller objects. Most of the code is more tedious and rote than creative. It should be more automated somehow IMO. Ive heard rumors that this is much improved in Panther - can anyone confirm and possibly explain?
jdh30
2005.12.30, 06:40 AM
I have been using OCaml in industry for the last couple of years. It is an excellent language and I have not yet had a single serious problem with it. Like any language, it does have some caveats but these are few and far between compared to languages like C++.
Although I have many more years of experience with C++, I am finding that I can already develop software in OCaml around 10x faster than I could in C++. OCaml makes incremental development much easier, primarily because functional programming leads to much cleaner separation of code and much less code duplication, and iterative improvements (even fundamental ones) require far fewer alterations in OCaml than they do in C++.
Performance is excellent. The biggest application I have written (25kLOC of OCaml) is 5x faster than the C++ version that took me a lot longer to develop and required several times as much code.
The OCaml community are also very helpful, and the OCaml mailing lists typically get any questions answered quickly and accurately. In an attempt to give back to the community, I am publishing lots of open-source OCaml programs:
http://www.ffconsultancy.com/free/
I have written some web pages explaining the benefits of the OCaml programming language:
http://www.ffconsultancy.com/free/ocaml/
and I have written a book on OCaml (aimed at computational scientists):
http://www.ffconsultancy.com/products/ocaml_for_scientists/
The first chapter is freely available as PDF and HTML and it should give anyone a decent introduction to the language.
I am considering writing a book on OCaml for Games Programming.
Cheers,
Jon.
jdh30
2006.01.05, 04:40 AM
If you only only want to count lines of code, I can do that in one line in C++:
transform(array.begin(), array.end(), array.begin(), bind2nd(plus<int>(), 1));
:D
The OCaml equivalent to that one line of C++ is actually:
map ((+) 1)
The genericity of C++'s "transform" (it can be applied to any data structure whereas OCaml must use a "map" function for a specific data structure, e.g. Lisp.map or Array.map) is traded for more pedantic static type checker and the ability to pass arbitrary functions (including closures) without having to use magic like bind2nd.
Seriously though, this isn't a lines-of-code contest. My experience with functional languages is minimal at best (very basic experimentation with Haskell), but I can see many advantages. As a "math" guy the declarative nature of functional languages really appeals to me. I'd love to implement some real-world problem in a functional language to see for myself the advantages/disadvantages over C++ (the procedural language I work in most often), but I don't think I can convince the guys at work to go for that.
It only took me 6 months of working with OCaml before I could write the majority of my software much more easily in OCaml than in C++. Now I consult for other people on OCaml. I'd estimate that development in OCaml (for numerical, visualisation and GUI software in my case) is 10x faster than in C++.
And here's why... when I think about it, very little of my time is spent defining algorithms, or even debugging algorithms. When I think about this, the benefits of a function language start to fade. How is a functional language going to help me interface with a SQL database better?
The more expressive type systems of languages like OCaml allow you to write APIs that convey much more information. What was documentation in C++ often becomes machine-verified specification in OCaml.
How is it going to help me create a GUI?
I find that programs are often best written with an imperative front-end (GUI) and a functional back-end. Most functional languages (including OCaml) support imperative programming as well. The advantages of the functional aspects are things like the ease of specifying callback functions.
How is it going to help me parse text files better?
That's easy - the ML family of languages (including OCaml) were specifically designed for writing compilers and interpreters. They come with very powerful lexer and parser generators which require much less code than C++ parsers, are much better statically checked and vastly easier and quicker to develop.
jdh30
2006.01.05, 05:19 AM
That does help a lot, thanks. With this thread and this online book (http://caml.inria.fr/oreilly-book/html/index.html), it's all starting to come together.
You may also like to read the freely available first chapter of my book, OCaml for Scientists (http://www.ffconsultancy.com/products/ocaml_for_scientists/).
Any idea why they are called "closures"?
They are "closed off from their environment". This means that the definition of a local closure can capture environment such as local variables. This makes garbage collection essential as local variables can outlive the function they are defined in if they are captured by a closure with is returned in the result of the function.
Cheers,
Jon.
Just a few general observations:
IMO, it is a good idea to experiment with as many programming languages as you have time for. Each language brings in new ideas that are favoured by the implementation, and often the ideas carry to other languages and improve your overall programming. Also, you should choose that programming language that applies best to your problem at hand.
On the other hand, doing things in a well established language has the advantages of a large community and well supported dev tools.
I believe every language has its place, and that functional languages are not particularly well suited to games, where it very often comes down to doing data shuffling close to the hardware. Not that I don't beat my head on the table from time to time because of coding in C/C++, it's just how I feel about it.
vBulletin® v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.