Functional programming gains popularity in recent years. Many main-stream imperative languages, e.g. C++11 and Java8, are adding functional features (actually templates in C++ are fully functional). Some new languages such as Scala even go further with comprehensive functional supports in an object-orient way. In this series, I will give an introduction to an elegant functional language OCaml, derived from ML. ML-derived languages are well known for their static type systems and type-inferring compilers. Unlike purely functional programming languages such as Haskell, ML/OCaml allows imperative programming that has side-effects. Moreover, OCaml supports object-oriented programming with an interesting design that is very different from class-based approach in C++/Java or message-based approach in Smalltalk/Ruby.
OCaml is very expressive and OCaml programs are concise and clean (but hard to understand for beginners). OCaml’s static type system helps eliminate runtime problems. On the other hand, its type-inferring compiler greatly reduces the need for manual type annotations. Compared to most academia-origined programming languages, OCaml puts a lot of emphasis on performance, which is very important for the use in industry. New languages like F# and Scala are strongly influenced by OCaml. In fact, F# is largely based on OCaml except objects, functors, and polymorphic variants. Therefore, F# even features a legacy “ML compatibility mode” which allow programs written in a large subset of OCaml to be immediately compiled as F#.
Before diving into the details of OCaml, let’s have a light discussion on what’s functional programming from a programmer’s point of view, which will be very helpful to understand the designs of OCaml. For some programmers (e.g. who use JavaScript), functional programming means lambdas (i.e. anonymous functions) and closures. Well, a Java programmer may argue that the inner class does achieve the same effects (of course, less pleasingly succinct). Some people claim that functional programming treats the computation as the evaluation of functions and thus the whole program can be regarded as a single function. While it is true, a C program can also be regarded as a single main function but it is clearly not functional. Interestingly, OCaml has no main entry function at all. Furthermore, people argue that the signature of functional languages is that functions are first-class citizens. Specifically, this means that the language supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables or storing them in data structure. But we can do all of these in C with function pointers. Of course, there are people talking about the immutable data in functional programming. Clearly immutable data are supported by const keyword in many imperative languages.
All above features touch some parts of function programming but fails to come to the key – functions in functional programming are pure mathematical functions that produce results that depend only on their inputs and not on the program state. In contrast, functions in imperative languages are just subroutines (i.e. a group of statements) for the purpose of code reuse, which may have side effects. Eliminating side effects can make it much easier to understand and predict the behavior of a program, which is one of the key motivations for the development of functional programming. Note that side effects could be useful in some cases, e.g. I/O and pseudo random number generators.
Theoretically, functional programming has its roots in lambda calculus. Many functional programming languages can be viewed as elaborations on the lambda calculus, where computation is treated as the evaluation of mathematical functions (don’t forget it) and avoids state and mutable data. But I won’t go further on this math heavy topic in case scaring away potential readers. In the next post, I will cover the basic building blocks of OCaml programs – expressions.
Pingback: OCaml: Expressions | Haifeng's Random Walk
Nice introduction. Functional programming really is just about programming without side effects: functions operate only on data supplied as arguments. You can do this in many languages through discipline, but some language encourage or enforce it. Functional programming yields very testable code, that is easily refactored and restructured, and naturally thread-safe. You don’t need advanced math to understand that!
Yes, it is not necessary to understand lambda calculus and type theory for functional programming. In fact, functional programming doesn’t even require a functional language. The discipline is more important. On the other hand, beyond avoiding side effects, functional languages do provide a lot of expressive features that make programming concise and efficient.
BTW, it is still better for language creators to dive into lambda calculus and type theory. Although not many people will create their own general-purpose languages, there are more and more DSLs/DSELs to solve various domain problems. A good foundation is always helpful.
Pingback: Awesome OCaml – Massive Collection of Resources – Learn Practice & Share