6.1 Metafunction Mu

The reader might have noticed that in our language as it has been defined up to this point, there were no means to apply a function whose name is not given explicitly but is the value of some variable or a result of computation. According to the syntax of Refal, after an opening activation bracket a symbolic function name (identifier) must necessarily follow. This requirement, which of course, is introduced for the purpose of efficient implementation, prevents us from using expressions such as:

  <sF eX> 
which we might write to call a function whose name is determined dynamically as the value of the variable sF . However, Refal-5 allows us to achieve the same effect by using the expression:
  <Mu sF eX> 
Here Mu is a built-in function, or rather, a metafunction which calls the function with the name given by the symbol immediately following Mu . The remaining part of the expression becomes the argument of the function. Thus Mu works as if defined by the sentence:
  Mu { sF eX = <sF eX> }
if it were syntactically admissible.

Using Mu we can define various kinds of interpreters which use expressions as programs specifying which of the lower-level functions (functions-executors) must be called. Here is a simple example of an interpreter which sequentially applies a given list of operations to a given argument:

  Use-seq 
    (sF e1) On eX = <Use-seq (e1) On <Mu sF eX>>;
    () On eX = eX; 

The modular structure of programs in Refal-5 brings a slight complication to the simple idea of Mu . Suppose you have used the function Mu to define some function Callmu in one module and then use Callmu as en external function in another module. It may happen that some function name is used in both modules to define different local functions. Which of the functions must be called then by Mu ? Specifically, consider the following two modules -- Mod1 :

  * This module is the main module Mod1.
  * It uses the function Callmu defined in Mod2. 
  * It also defines function F
  * which has a different definition in Mod2.
  $ENTRY Go { =  <Prout 'Mu: ' <Mu F 'ABC'>> 
         <Prout 'Callmu: ' <Callmu F 'ABC'>> }
  $EXTRN Callmu;
  F { e1 = 'Mod1' }
and Mod2 :
  * This auxiliary module is Mod2. It defines 
  * a simple interpreting function Callmu,
  * which uses Mu. It also defines function F
  * which is defined differently in Mod1.
  $ENTRY Callmu { sF eX = <Mu sF eX>; }
  F { e1 = 'Mod2' }

We can define two versions of the metafunction Mu : Mu-Static MuS , and Mu-Dynamic MuD . With the static definition, the functional meaning of a symbolic name is defined by the module where the function using MuS is written; in our case this is Mod2 . The general rule is: wherever a call of MuS appears, it can activate only a function visible from this point (i.e., either locally defined or entering an $EXTERN list), and the function called will be the one defined at that point. With the dynamic definition, the functional meaning of a symbolic name is as defined at the execution time, i.e., in the main module: Mod1 in our case. Let us execute:

  refgo Mod1+Mod2
If Mu is defined statically (as MuS ), the program will print out:
  Mu: Mod1
  Callmu: Mod2
If Mu is defined dynamically (MuD ), the print-out will be:
  Mu: Mod1
  Callmu: Mod1

There is something to be said both for and against each of the ways to define Mu . The dynamic definition seems more natural and it sticks to the general principle: if a function is not visible from the main module, it cannot be activated. On the other hand, from the systems viewpoint it is good to be able to call any function of the program, if necessary. MuD does not allow this while MuS does. Indeed, let the names of the modules we are using be Mod1 , Mod2 , Mod3 , etc. In Mod1 we define:

  $ENTRY Mu-Mod1 { e1 = <Mu e1> } 
in Mod2 :
  $ENTRY Mu-Mod2 { e1 = <Mu e1> } 
etc. Then whenever we want to call functions as defined in some module Modi , we call Mu-Modi (do not forget to include this function in the $EXTERN list). The dynamic function MuD can be simulated using the static function Mu . We only have to define:
  $ENTRY MuD { e1 = <Mu e1> } 
in the main module and then use MuD in any module (again, declaring it as external outside of the main module).

Having this in mind, the built-in function Mu has been defined statically in our Refal system.

Exercise 6.1 Suppose you have defined fifty functions with the names Fun1 , Fun2 ... etc. to Fun50 . Define the function Fun-n so that <Fun-n sN eX> calls the sN 'th function of this series with the argument eX . Example:

  <Fun-n 12 'ABC'>       becomes     <Fun12 'ABC'>