Skip to content
Stephen Leach edited this page Oct 18, 2020 · 5 revisions

When a procedure does not make any side-effects, it is said to be clean. Clean procedures are only allowed to call other clean procedures, finesses or functions - none of which can have any side-effects. They cannot perform any I/O directly and nor can they update objects directly or indirectly.

Clean procedures have a lot more freedom than finesses or functions. For example they are allowed to create mutable store and return it (but not mutate it) and they are allowed to take mutable arguments (but not mutate them). Like finesses they are free to use var variables internally and loops too. As a coder, you can declare a procedure to be @clean and the compiler will check this for you. The compiler actually determines the cleanliness of every procedure and uses this information to perform that check.

@clean
def revAppend( x, y ):
    ### x and y may be mutable lists, we don't mind.
    [ y.items(), x.items() ]
end

@clean
def sumList( list ):
    var sofar := 0
    for i in list do
        sofar <- sofar + 1
    endfor
end

Of course assignment is not allowed in pure functional style and you might prefer to explicitly exclude the use of var variables. To do this you require declarations to be val or better with the @inputs(val) annotation, that only allows val or const modifiers.

@clean @inputs(val)
def sumList( list ):
    reduce( nonop +, list, 0 )
end

Procedures fall into a hierarchy of function-ness in Nutmeg:

  1. General procedures that can do anything - just called procedures
  2. Clean procedures that can't use side effects but can only call cleans, finesses or functions - called clean procedures or 'cleans'
  3. Finesses that only accept and return const values and can only call other finesses or functions
  4. Functions that only accept and return const values, can't use side-effects and can only call other finesses or functions

Clone this wiki locally