Function and procedure behave differently with the same code in Mozart Oz?

4.3k views Asked by At

I try printing out the Fibonacci sequence in Oz using 2 approach : function and procedure using Emac as editor. Procedure goes here :

declare 
fun {Fibo N} 
   case N of 
      1 then 1 
   [] 2 then 1
[] M then {Fibo (M-1)} + {Fibo (M-2)} 
   end 
end 
declare
proc {Loop K}
   if K ==1 then  {Browse K}
   else
      {Loop K-1}
       {Browse {Fibo K}}
   end
end
{Loop 10}

and function:

declare 
fun {Fibo N} 
   case N of 
      1 then 1 
   [] 2 then 1
[] M then {Fibo (M-1)} + {Fibo (M-2)} 
   end 
end
declare
fun {Loo L}
   if L ==1 then  {Browse L}
   else
      {Loo L-1}
       {Browse {Fibo L}}
   end
end
{Loo 10}

The problem is the only Procedure "Loop" works. Result is:

1
1
2
3
5
8
13
21
34
55

Function "Loo" doesn't and it throws some hard-to-understand errors:

%********************** static analysis error *******************
%**
%** illegal arity in application
%**
%** Arity found:          1
%** Expected:             2
%** Application (names):  {Loo _}
%** Application (values): {<P/2> _<optimized>}
%** in file "Oz", line 13, column 6

%********************** static analysis error *******************
%**
%** illegal arity in application
%**
%** Arity found:          1
%** Expected:             2
%** Application (names):  {Loo _}
%** Application (values): {<P/2> 10}
%** in file "Oz", line 17, column 0
%** ------------------ rejected (2 errors)

I still don't know why. As I think function and procedure has similar effect in OZ.

2

There are 2 answers

2
wmeyer On BEST ANSWER

Functions must be called either with function call syntax:

_ = {Loo 10}

or alternatively with an additional parameter to receive the value:

{Loo 10 _}

_ is pronounced "don't care" and means that the value of the variable is not needed.

Also, functions must return a value by having an expression as the last part of every branch. So your fixed Loo function would look like this:

fun {Loo L}
   if L == 1 then
      {Browse L}
      unit
   else
      _ = {Loo L-1}
      {Browse {Fibo L}}
      unit
   end
end
_ = {Loo 10}

However, using a function for looping like this does not make much sense if you don't have anything interesting to return. Maybe what you really want is to build a list and return it as the result?

0
Håvard S On

You have a typo in the definition of Loo at line 13.

You're calling Loop, which does not exist. I assume you should be calling Loo.

UPDATE: What you are seeing is due to the difference between functions and procedures; functions always return values, procedures don't. You are giving a single argument to Loo (K-1), but Loo needs two arguments; one input variable and one variable to capture the return value. Oz tells you this by saying that you're applying the wrong arity to Loo (you're applying one argument (unary) when you should be applying two arguments (binary)).

This means you have to assign the return value to a variable as well. Do one of:

  1. A = {Loo K-1}
  2. {Loo K-1 A}

A is the variable to which the return value will be assigned. A common convention for cases where you don't care what the function returns is to use _ as the return variable name.