PreviousUpNext

5.4.2  Mythryl Functions: Beyond Parameter Lists

To date we have been fostering the illusion that Mythryl functions are much like functions in C or Perl, give or take the occasional syntactic oddity or feature.

In this section we draw aside the veil.

C functions are hardwired by the compiler to accept a comma-delimited sequence of parameters. The C grammar specifies exactly what that parameter sequence may contain; the C compiler translates directly from ordinal position within the parameter sequence to ordinal position within a stackframe. As far as the C compiler is concerned, a function parameter list declaration is essentially an abstract specification of part of a function call stackframe.

The Mythryl compiler doesn’t see function syntax that way at all.

To start with, the Mythryl compiler does not think of functions as having multiple parameters matching multiple arguments. So far as the Mythryl compiler is concerned, every Mythryl function takes exactly one value as input and returns exactly one value as result. (This turns out to make the compiler much simpler to write!)

What we have been presenting as a conventional function argument list, the Mythryl compiler has all along been thinking of as a single tuple argument.

At first blush this may appear to be a purely philosophical distinction about as important to today’s practicing programmer as is the distinction between Homoiousian and Homoousian to today’s practicing Christian. (There was a time when confusing the two could get you killed!)

In fact, there is a world of difference between the two ways of thinking about the matter, and until you begin thinking about it the Mythryl way, you are not writing Mythryl at all, really, but rather writing C in Mythryl syntax.

Let us start with a simple example. The fact that the Mythryl “argument lists” we have been writing are in fact tuple arguments means that we can construct such “argument lists” ahead of time, pass them around, and even store them in other datastructures, before finally applying the function to them. Do not try any of these examples in C!

    #!/usr/bin/mythryl

    fun confess (name, condition) = {
        printf "Hello!  My name is %s and I am %s.\n"  name  condition;
    };

    confess( "Linus", "an open source programmer" );

    a = ( "Richard", "a free software author" );

    confess a;

    b = [ ( "Albert", "a physicist" ),
          ( "Karl",   "a mathematician" )
        ];

    map confess b;

When run this produces

    linux$ ./my-script
    Hello!  My name is Linus and I am an open source programmer.
    Hello!  My name is Richard and I am a free software author.
    Hello!  My name is Albert and I am a physicist.
    Hello!  My name is Karl and I am a mathematician.
    linux$ 

So already we can begin to see that this fresh way of thinking about functions is opening up fresh expressive possibilities for coding.

Now let us open up the world of possibilities a bit more.

The Mythryl compiler does not think of functions as accepting a single tuple as argument. That is not what we said above. The Mythryl compiler thinks of functions as accepting a single value as argument. Any type of of value will do.

In particular, the argument value handed to a function can just as easily be a record as a tuple. The Mythryl compiler hardly distinguishes between the two anyhow; to it a record is just a tuple with a teeny bit of extra icing on top.

This essentially means that we get functions with keyword arguments “for free” in Mythryl, where some other languages devote just a remarkable amount of special-case jiggery-pokery logic in the compiler to implementing them:

    #!/usr/bin/mythryl

    fun confess { name, condition } = {
        printf "Hello!  My name is %s and I am %s.\n"  name  condition;
    };

    confess { name => "Linus", condition => "an open source programmer" };

    a = { name => "Richard", condition => "a free software author" };

    confess a;

    b = [ { name => "Albert", condition => "a physicist" },
          { name =>  "Karl", condition => "a mathematician" }
        ];

    map confess b;

When run, this produces exactly the same results as the first script, and in fact may well compile into exactly the same binary code, but the readability impact is significant. In particular, the intent behind the list of records is immediately much clearer to the reader than is that behind the earlier list of tuples.

Record arguments are particularly nice when a function has two arguments of the same type which might easily be confused.

For example when copying from one vector to another (say), the programming world has no consistent convention as to whether the destination should come first or second. It is easy to get them backwards, and the result is an error which will not be caught at compiletime and which might take some time to track down at runtime.

Using record instead of tuple arguments can make the code clearer and reduce the risk of introducing errors during code maintenance:

    copy (        this_vector,        that_vector );    # Potentially confusing
    copy { src => this_vector, dst => that_vector };    # Much clearer.

Comments and suggestions to: bugs@mythryl.org

PreviousUpNext