Search code examples
ozmozart

Argument error in my "For" loop code (Oz/Mozart)


I've started to learn Oz/Mozart recently, and for practice, I'm trying to write the code of a simple "For" procedure, that loops from "Init" to "End" values, and in each cycle print the current cycle number to the Browser. Here is the code:

This procedure creates a list from Init to End value:

declare
fun {Listing Init End}
   if Init == End then
      [Init]
   else
      Init|{Listing Init+1 End}
   end
end

This do the loop and applies the function "F" in each cycle:

declare ForList
fun {ForList F L}
   case L of H|T then
      {F H}|{ForList F T}
   else nil end
end

This wrap the above functions, so that can work receiving Init and End values, instead of a list:

declare MyFor L X in
proc {MyFor F Init End}
   L = {Listing Init End}
   X = {ForList F L}
end

Finally, I call MyFor:

{MyFor Browse 1 4}

When I try to compile, I get this error:

%*************** Error: illegal number of arguments *************
%**
%** In statement: {<P/1 Browse> 1 _<optimized>}
%** Expected:     1 argument
%** Found:        2 arguments
%**
%** Call Stack:
%** procedure 'ForList' in file "Oz", line 11, column 0, PC = 15793

(The line 11 is "fun {ForList F L}")

I've tried swaping "func" and "proc" in some of the subroutines to see if something changes, but I really don't know what I'm doing wrong.


Solution

  • ForList expects a function that maps elements to a result. But Browse is a procedure that does not return anything. ForList should probably look more like this:

    proc {ForList F L}
      case L of H|T then
        {F H}
        {ForList F T}
      else
        skip
      end
    end
    

    This is exactly the difference between the built-in function List.forAll and List.map.

    BTW, in the definition of MyFor you are using global variables X and L. This will cause problems when MyFor is called more than once. You should use local variables instead. Like so:

    proc {MyFor F Init End}
      L X
    in
      L = {Listing Init End}
      X = {ForList F L}
    end