<< Prev | - Up - | Next >> |

Oz provides functional notation as syntactic convenience. We have seen that a procedure call:

`{P X1 ... Xn R}`

could be used in a nested expression as a function call:

`{P X1 ... Xn}`

Oz also allows functional abstractions directly as syntactic notation for procedures. Therefore, the following function definition:

`fun {F X1 ... Xn}`

S

E`end`

where *S* is a statement and *E* is an expression corresponds to the following procedure definition:

`proc {F X1 ... Xn R}`

S`R=`

E`end`

**Warning:**The exact syntax for functions as well as their transformation into procedure definitions is defined in the *The Oz Notation Reference Manual*.

Here we rely on the reader's intuition. Roughly speaking, the general rule for syntax formation of functions looks very similar to how procedures are formed. With the exception that, whenever a thread of control in a procedure ends in a statement, the corresponding function ends in an expression.

The program shown in Figure 6.1 is the functional equivalent to the program shown in Figure 5.7. Notice how the function `AndThen/2`

is unfolded into the procedure `AndThen/3`

. Below we show a number of steps that give some intuition of the transformation process. All the intermediate forms are legal Oz programs.

`fun {AndThen BP1 BP2}`

if {BP1} then {BP2}

else false end

end

Make a procedure by introducing a result variable `B`

:

`proc {AndThen BP1 BP2 B}`

B = if {BP1} then {BP2}

else false end

end

Move the result variable into the outer *if-expression* to make it an *if-statement*:

`proc {AndThen BP1 BP2 B}`

if {BP1} then B = {BP2}

else B = false end

end

`% Syntax Convenience: functional notation`

local

fun {AndThen BP1 BP2}

if {BP1} then {BP2}

else false end

end

fun {BinaryTree T}

case T

of nil then true

[] tree(K V T1 T2) then

{AndThen

fun {$} {BinaryTree T1} end

fun {$} {BinaryTree T2} end}

else false end

end

end

If you are a functional programmer, you can cheer up! You have your functions, including higher-order ones, and similar to lazy functional languages Oz allows certain forms of tail-recursion optimizations that are not found in certain strict functional languages ^{1} including Standard ML, Scheme, and the concurrent functional language Erlang. However, standard function definitions in Oz are not lazy. Lazy functions are also supported in Oz^{2}.

Here is an example of the well-known higher order function `Map/2`

. It is tail recursive in Oz but not in Standard ML or in Scheme.

`fun {Map Xs F}`

case Xs

of nil then nil

[] X|Xr then {F X}|{Map Xr F}

end

end

{Browse {Map [1 2 3 4] fun {$ X} X*X end}}

`andthen`

and `orelse`

After all, we have been doing a lot of work for nothing! Oz already provides the Boolean lazy (non-strict) versions of the functions `And/2`

and `Or/2`

as the Boolean operators `andthen`

and `orelse`

respectively. The former behaves like the function `AndThen/2`

, and the latter evaluates its second argument only if the first argument evaluates to `false`

. As usual, these operators are not primitives, they are defined in Oz. Figure 6.2 defines the final version of the function `BinaryTree`

.

`fun {BinaryTree T}`

case T of nil then true

[] tree(K V T1 T2) then

{BinaryTree T1} andthen {BinaryTree T2}

else false end

end

Since now, in principal, we have some syntactic redundancy by either using procedures or functions, the question is when to use functional notation, and when not. The honest answer is that it is up to you! I will tell you my personal opinion. Here are some rules of thumb:

First, what I do not like. Given that you defined a procedure

`P`

do not call it as a function, i.e. do not use functional nesting for procedures. Use instead procedural nesting, with nesting marker, as in the`SMerge`

example. Moreover, given that you defined a function, call it as function.I tend to use function definitions when things are really functional, i.e. there is one output and, possibly many inputs, and the output is a mathematical function of the input arguments.

I tend to use procedures in most of the other cases, i.e. multiple outputs or nonfunctional definition due to stateful data types or nondeterministic definitions

^{3}.One may relax the previous rule and use functions when there is a clear direction of information-flow although the definition is not strictly functional. After all functions are concise.

<< Prev | - Up - | Next >> |

1. Strict functional languages evaluate all its argument first before executing the function

2. We will discuss them later when talking about *futures* and by need synchronization

3. In fact, in those cases the use of the object-oriented style of Oz is most appropriate

Seif Haridi and Nils Franzén

Version 1.4.0 (20080702)