Search code examples
functionprocedureozmozart

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


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.


Solution

  • 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?