Logo Search packages:      
Sourcecode: mathpiper version File versions  Download package


/* {{{ License.
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */ //}}}

// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0:
package org.mathpiper.builtin.functions.core;

import org.mathpiper.builtin.BuiltinFunction;
import org.mathpiper.lisp.Environment;

public class DefMacroRulebase extends BuiltinFunction

    public void evaluate(Environment aEnvironment, int aStackTop) throws Exception
        org.mathpiper.lisp.Utility.defMacroRuleBase(aEnvironment, aStackTop, false);

%mathpiper_docs,name="DefMacroRuleBase",categories="Programmer Functions;Programming;Built In"
*CMD DefMacroRuleBase --- define a function as a macro


{name} -- string, name of a function

{params} -- list of arguments


{DefMacroRuleBase} is similar to {RuleBase}, with the difference that it declares a macro,
instead of a function.
After this call, rules can be defined for the function "{name}", but their interpretation will be different.

With the usual functions, the evaluation model is that of the <i>applicative-order model of
substitution</i>, meaning that first the arguments are evaluated, and then the function
is applied to the result of evaluating these arguments. The function is entered, and the
code inside the function can not access local variables outside of its own local variables.

With macros, the evaluation model is that of the <i>normal-order model of substitution</i>,
meaning that all occurrences of variables in an expression are first substituted into the
body of the macro, and only then is the resulting expression evaluated <i>in its
calling environment</i>. This is important, because then in principle a macro body
can access the local variables from the calling environment, whereas functions can not do that.

As an example, suppose there is a function {square}, which squares its argument, and a function
{add}, which adds its arguments. Suppose the definitions of these functions are:

      add(x,y) <-- x+y;
      square(x) <-- x*x;
In applicative-order mode (the usual way functions are evaluated), in the following expression
first the arguments to {add} get evaluated. So, first {square(2)} is evaluated.
To evaluate this, first {2} is evaluated, but this evaluates to itself. Then
the {square} function is applied to it, {2*2}, which returns 4. The same
is done for {square(3)}, resulting in {9}. Only then, after evaluating these two
arguments, {add} is applied to them, which is equivalent to
resulting in calling {4+9}, which in turn results in {13}.

In contrast, when {add} is a macro, the arguments to {add} are first
expanded. So
first expands to
      square(2) + square(3)
and then this expression is evaluated, as if the user had written it directly.
In other words, {square(2)} is not evaluated before the macro has been fully expanded.

Macros are useful for customizing syntax, and compilers can potentially
greatly optimize macros, as they can be inlined in the calling environment,
and optimized accordingly.

There are disadvantages, however. In interpreted mode, macros are slower,
as the requirement for substitution means that a new expression to be evaluated
has to be created on the fly. Also, when one of the parameters to the macro
occur more than once in the body of the macro, it is evaluated multiple times.

When defining transformation rules for macros, the variables to be substituted
need to be preceded by the {@} operator, similar to the back-quoting mechanism.
Apart from that, the two are similar, and all transformation rules can also be
applied to macros.

Macros can co-exist with functions with the same name but different arity.
For instance, one can have a function {foo(a,b)}
with two arguments, and a macro {foo(a,b,c)} with three arguments.


The following example defines a macro {myfor}, and shows one use, referencing
a variable {a} from the calling environment.

      In> DefMacroRuleBase("myfor",{init,pred,inc,body})
      Out> True;
      In> myfor(_init,_pred,_inc,_body)<--[@init;While(@pred)[@body;@inc;];True;];
      Out> True;
      In> a:=10
      Out> 10;
      In> myfor(i:=1,i<10,i++,Echo(a*i))
      Out> True;
      In> i
      Out> 10;

*SEE RuleBase, Backquoting, DefMacroRuleBaseListed

Generated by  Doxygen 1.6.0   Back to index