
Calling Sequence


option inline


Description


•

An inline procedure avoids the overhead of a procedure call by executing the Maple instructions directly, as if it were written inline, rather than in a separate procedure. For simple procedures, this can make the code more efficient.

•

A procedure can be made subject to inlining by including the option inline in its option declaration. For example:

f := proc(x) option inline; op(2,x) end proc;




This will cause any calls to f that are simplified while f is defined to be expanded inline.

•

Only very simple procedures can be expanded inline. The following restrictions limit the procedures that can be inlined:

–

The body of the procedure must consist of a single expression or expression sequence; it cannot consist of a statement or statement sequence.

–

The procedure cannot have any local or lexically scoped variables.


If a procedure with option inline does not meet these requirements, an exception is raised when the procedure is first simplified.

•

Even if a procedure meets all the requirements for being inlined, not every invocation of it will necessarily be inlined. A procedure will only be inlined at an invocation point when the following requirements are met:

–

The number of actual parameters in the unevaluated procedure call matches the number of formal parameters of the procedure.

–

The definition of the procedure is known (meaning that it has been executed, and not just parsed, before a call to it is simplified).

–

The procedure does not call itself recursively.

•

Due to the differences between calling a procedure or just executing its body (with appropriate substitutions) inline, semantic differences will inevitably occur between called and inline invocation. Most of the semantic differences between called and inline procedure invocations are in the area of parameter evaluation.

•

When a procedure is called, the actual parameters are first evaluated. If any of the actual parameters evaluates to an expression sequence, then the individual elements of such a sequence become individual actual parameters. When a procedure call is expanded inline, the unevaluated actual parameters are substituted for the formal parameters in the expanded procedure body, meaning that an actual parameter whose value is an expression sequence is considered as a single parameter.

•

If a formal parameter is used more than once in a procedure that is expanded inline, the actual parameter will be evaluated more than once. If this evaluation has sideeffects, the result can be different than if the procedure was called. Likewise, a formal parameter that is never used will cause the corresponding actual parameter to never be evaluated at all.

•

Inline procedures that make use of args, nargs, or procname have these values expanded at inline expansion time. Specifically, args expands to the expression sequence of unevaluated actual parameters, nargs expands to the number of actual parameters (which by definition must equal the number of formal parameters), and procname expands to the name by which the procedure was called.

•

If a procedure has typed parameters (for example, x::integer), the parameter type checking is not done if the procedure is expanded inline. Therefore, inline procedures should either perform type checking as part of the procedure body expression, or should be used only where there is no danger of calling them with the wrong type of parameter.

•

Inline expansion is done at simplification time. If a procedure is defined with option inline, then a second procedure is defined to call this first procedure, and then the first procedure is redefined. The second procedure retains the inline expansion of the original definition of the procedure.

•

Procedure inlining can be disabled with the call kernelopts(inline=false), and reenabled with kernelopts(inline=true). Note that changing this setting will not retroactively do or undo inline expansions.



Examples


>

sq := proc(x) option inline; x^2 end proc;

${\mathrm{sq}}{:=}{\mathbf{proc}}\left({x}\right)\phantom{\rule[0.0ex]{0.5em}{0.0ex}}{\mathbf{option}}\phantom{\rule[0.0ex]{0.5em}{0.0ex}}{\mathrm{inline}}{\;}\phantom{\rule[0.0ex]{0.5em}{0.0ex}}{x}{\^}{2}\phantom{\rule[0.0ex]{0.5em}{0.0ex}}{\mathbf{end\; proc}}$
 (1) 
>

hypot := proc(a,b) sqrt(sq(a)+sq(b)) end proc;

${\mathrm{hypot}}{:=}{\mathbf{proc}}\left({a}{\,}{b}\right)\phantom{\rule[0.0ex]{0.5em}{0.0ex}}{\mathrm{sqrt}}{}\left({a}{\^}{2}{\+}{b}{\^}{2}\right)\phantom{\rule[0.0ex]{0.5em}{0.0ex}}{\mathbf{end\; proc}}$
 (2) 
>

quad := proc(a,b) sq(a+b) * sq(ab) end proc;

${\mathrm{quad}}{:=}{\mathbf{proc}}\left({a}{\,}{b}\right)\phantom{\rule[0.0ex]{0.5em}{0.0ex}}\left({a}{\+}{b}\right){\^}{2}{\*}\left({a}{}{b}\right){\^}{2}\phantom{\rule[0.0ex]{0.5em}{0.0ex}}{\mathbf{end\; proc}}$
 (3) 
Inlining does not work here because the first procedure definition
has not yet been executed when the second one is simplified.
>

module M() export f, g;
f := proc(x) option inline; x^3 end proc;
g := proc(a,b) f(a+b) end proc
end module;

${\mathbf{module}}\phantom{\rule[0.0ex]{0.5em}{0.0ex}}{M}\left({}\right)\phantom{\rule[0.0ex]{0.5em}{0.0ex}}{\mathbf{export}}\phantom{\rule[0.0ex]{0.5em}{0.0ex}}{f}{\,}{g}{\;}\phantom{\rule[0.0ex]{0.5em}{0.0ex}}{}\phantom{\rule[0.0ex]{0.5em}{0.0ex}}{\mathbf{end\; module}}$
 (4) 
>

$\mathrm{print}\left(M:g\right)$

${\mathbf{proc}}\left({a}{\,}{b}\right)\phantom{\rule[0.0ex]{0.5em}{0.0ex}}{\mathrm{`M:f`}}{}\left({a}{\+}{b}\right)\phantom{\rule[0.0ex]{0.5em}{0.0ex}}{\mathbf{end\; proc}}$
 (5) 
It does work here though, because M:f is now known.
>

h := proc(a,b) M:f(ab) end proc;

${h}{:=}{\mathbf{proc}}\left({a}{\,}{b}\right)\phantom{\rule[0.0ex]{0.5em}{0.0ex}}\left({a}{}{b}\right){\^}{3}\phantom{\rule[0.0ex]{0.5em}{0.0ex}}{\mathbf{end\; proc}}$
 (6) 


