Skip to content

Functional haXe

I recently took some time to learn Clojure, a Lisp dialect I’ve also
investigated newLisp, OCaml and F#, here are some thoughts on how to
include functional techniques in your haXe programming.

haXe is ostensibly an OOP language but a functional style can be
adopted in the vein of “Javascript the Good Parts”.

Disclaimer: I have always been an OOP and class based programmer, so
to existing functional programmers this is a ‘big whatever’.

Some Material

I really recommend watching Rich Hickey’s talks introducing Clojure
for Java programmers http://blip.tv/file/982823, where he really
lays it out. All Rich’s talks are worth watching.

Another talk by Yaron Minsky of Jane Street Capital
http://ocaml.janestreet.com/?q=node/61, on OCaml is interesting in
references to “discriminated unions”, known to us as recursive enums
with constructors.

Don Syme’s introduction to F# also good
http://channel9.msdn.com/posts/Charles/Don-Syme-Introduction-to-F-Part-1/

Basic Functional Philosophy

  • Small number of data structures, large number of functions that work on them.
  • Functions should return the same result for the same parameter. If they don’t there is hidden state influencing the result. Functions with this attribute are called “pure”.
  • Functions as values. Functions can be assigned to variables and passed as parameters to other functions. AKA Higher Order Functions.

Class Hierarchy Overuse

To move to a functional style the first thing required is to be judicious in the use of
class hierarchies. Just start writing static functions using the class as a grouping
mechanism for related functions. What you find is you get to the heart of your problem
much faster – I wasted lot’s of time trying to model and think about the permutations of
a hierarchy. Just write the base functions.

  class Useful {

  public static function
  useful1() {
  ...
  }

  public static function
  useful2() {
  ...
  }

  }

This very much models “modules” in F# for example. Clojure has hierarchical namespaces
due to it’s Java heritage and the need to use existing libraries, but it’s core library
consists of 100 or so basic functions. The point is that pure functions can be used in
any combination without thought of class or hierarchy.

Of course, at some stage OOP is useful, but you’ll be amazed that you can defer it’s
use, and make a lot of complexity go away. Notice that the haXe standard libraries are
mostly constructed in this fashion, thanks to the OCaml influence.

State is Bad

All variables are sources of potential bugs, minimise their use. Strive to remove
variables, preferring functions that perform their calculations from first principles.

Unsurprisingly, class based languages have a tendency to make you want to create
classes, and classes have the tendency to make you want to create state; the purpose of
a class is to encapsulate state not eliminate it. Use classes atypically and reduce
state.

In conjunction with the note on class hierarchy above, the perfect pure function does
not rely on static variables residing in the class, except for constants.

For example, if you look at the haxed source code, ClientTools.hx is sizeable class but
it only has one static variable which is “bad”. The other functions defined within are
all pure, and use haXe inlining to mitigate the performance argument.

  public static inline function
  projectDir(prj) {
  return Os.slash(getRepos() + Common.safe(prj));
  }

  public static inline function
  versionDir(prj,?ver) {
  if (ver == null) ver = currentVersion(prj);
  return Os.slash(projectDir(prj) + Common.safe(ver));
  }

The functions only depend on their parameters – not on class state.

You can have variables in the ML’s and Clojure, however they are specially marked, and
Clojure goes one step further to provide language support for transactional concurrency
semantics.

Vars as Immutable References

The use of vars inside a function is acceptable, but use them like immutable
references, that is as names for values that are computed once only.

For example, here’s a fragment that has a large set of vars used in this way:

   var lwc = lowestWinner(game),
   winningCards = getWinningCards(game,lwc),
   byPlayer = SeqTools.groupBy("sessID",winningCards),
   totalWinners = winningCards.length,
   nPlayers = byPlayer.array().length,
   jpQualify = JP.qualify(game,lwc),
   jpVal = (jpQualify) ? -jackpot : 0,
   totalWin = cardCache.length * template.cardValue * games[game].prizePC + jpVal;

Notice that once the var ref is set it isn’t reset. Get a value in the name use it in a
further calculation. This is effectively using var as a let in OCaml or Clojure. Var
usage like this allows the composition of complex calculations.

Using … Lambda

There’s another use of variables in looping constructs which can be mitigated by the
Lambda class. The basics are:

Function Action
Lambda.map Apply a function to each element of a list transforming it in some way
Lambda.filter Apply a function to each element of a list returning true if you want it included
Lambda.fold Given a starting value, accumulate each element of the list in it.

The traditional means of calling Lambda is like this

var x = Lambda.map(names,function(n) {
    return StringTools.upperCase(n);
});

as a static function. If you don’t import Lambda but instead

using Lambda;

then you can use it like this

names.map(function(n) {
    return StringTools.upperCase(n);
});

of course StringTools.upperCase is already a function which takes a string and returns a
string so lets skip the middleman …

names.map(StringTools.upperCase);

The “using” facility is extremely powerful as it also allow “piping” of output from one
function into the next like this …

names
.filter(function(n) { return n == "blackdog" ;})
.map(StringTools.upperCase)

which is very similar to F#’s |> operator (in fact I’d prefer to see an operator in haXe
to rather than “using” as it’s limited to using external files and not functions I’ve
defined in this file.

Here’s a real example from haxed …

  function
  keySearch(k:String):List<ProjectTags> {
    var find = "find "+repoTop+" -maxdepth 2 -name *haxed -exec grep -H "+k+" {} \\;";
    return
      Os.process(find)
      .split("\n")
      .map(function(l) {
          var re = new EReg("^(\\S+)\\s*"+k+"\\s*(\\S.*)$","");
          return if (re.match(l)) {
                prj:Os.path(re.matched(1),NAME),
                val:re.matched(2).trim()
            } else null;
        })
      .filter(function(el) { return el != null ; });
  }

This is my favorite style, a function which returns right away with no side effects and is
based solely on it’s input not state.

Notice how I’m using the inner if as an expression and not as statement, this is also a
functional rule, everything is an expresssion. haXe follows this.

Here’s another example from the haxed file ServerGit.hx

  function
  findProjectsByTag(tag:String):List<String> {
    return
      keySearch("tags:")
      .map(function(el) { return { prj:el.prj,tags:el.val.split(" ") }; })
      .filter(function(el) {
          return el.tags.exists(function(e) { return e == tag; }) ; })
      .map(function(el) { return el.prj; });
  }

However this is not piping in the unix sense, in that there’s no producer/consumer here
working cooperatively per element. In fact, one possible problem is performance. An
iterative solution is possibly faster due to the fact that haXe creates new List() object
inside each map() function and then adds to them from the source. Here’s another example
of a fold using an inner for because i thought there could be too much object creation …

 function
  findTags():Array<String> {
    return
      keySearch("tags:")
      .fold(function(a:ProjectTags,b:Array<String>) {
          for (i in a.val.split(" "))
            if (i.trim() != "")
              b.push(i);
          return b;
        },new Array<String>());
  }

A fold takes the starting value, new Array<String>(), and accumulates the items from a
into it. In this instance i have project tags, e.g. “gtk gui”, which need split and
trimmed and then pushed onto the accumulator, which is passed into the function as
variable b.

I could have used another map and filter within the fold, but I decided that that would
incur too many new objects being created.

It could look like this instead

function
  findTags():Array<String> {
    return
      keySearch("tags:")
      .fold(function(a:ProjectTags,b:Array<String>) {
          return a
          .map(function(el) { return el.split(" "); })
          .filter(function(el) { return el.trim() != ""; })
          .array()
          .concat(b);
        },new Array<String>());
  }

I should have probably passed a list in and finally returned an array saving the
conversion to array.

Finally, the other name for fold is reduce, and is a better name in some ways, as you can
see that an accumulation reduces the size of the list to 1.

One Comment

Trackbacks & Pingbacks

  1. Haskell Liftoff « nodename

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: