# Functions - Functions accept a single input and produce an output. - All functions are inherently curried. ## Private Functions - Any function may be marked `private`. - `private` functions are only available in the current scope. - Scope is file, class, instance, etc. (any function holder) - `private` functions are NOT exported. ``` given F * class Functor given A, B fn map: (A -> B) -> F A -> F B end class instance Functor List given A, B fn map: (A -> B) -> [A] -> [B] case _ [] => [] case f [h : t] => f h : map f t end fn end instance ``` ``` map (+ 1) [1, 2, 3] -- produces [2, 3, 4] -- Assuming F is given, F A -> F B let plus_one := map (+ 1) ``` note define infix in parens as prefix!!! ``` given F * * Map String Int32 -- F[*[*]] given F (* *) List (List String) ``` ## Syntax ``` [given T1, T2, ... TN] fn : => end fn ``` - `TN`: Type declaration (e.g. A :: Show) - `name`: Follows the rules for [names](names.md) - `input`: One or more named tuples ([records](records.md)). - `output`: Some type. - `body`: Function definition. Note that ` => ` is the type of a function. ## Function Definitions Function definitions are a series of expressions, where the value of the last expression is returned. ``` fn example: (x: Int32, y: Int32) => Int32 let xx := x + 1 let yy := y + 1 xx * yy end fn ``` ## Calling Functions Calling a function involves passing that function the tuples it needs. ``` given A :: Show fn example: (a: A) => String show(a) end fn fn calling_a_function: () => Task[()] let x := 1 let y := true let z := "foo" println(show(x) + show(y) + show(z)) end fn ``` ### Calling with Tuples ``` fn example: (x: Int32, y: Int32: z: Int32) => Int32 x + y + z end fn let inputs := (10, 20, 30) example inputs ``` ``` fn example: (x: Int32, y: Int32)(z: Int32, w: Int32) => Int32 x + y + z + w end fn let in1 := (1, 2) let in2 := (3, 4) example in1 in2 example (1, 2) in2 example in1 (3, 4) ``` ## Generic Functions ## Referencing Arguments `@args` refers to function arguments. - For a single parameter list, it refers to the record. - For multiple parameter lists, it refers to a tuple containing the lists in order. ## Lazy Arguments The `lazy` keyword allows the expression providing the value to have evaluation deferred until the value is _used_ in the function. If the value is not used, the expression is never evaluated. ``` fn foo: (lazy x: Int32) => Int32 x * 2 end fn ``` Note that this is equivalent to encoding a parameter as a synchronous effect and evaluating it to value when needed. ## Function Composition ``` given A, B, C fn compose: (f: (B) => C, g: (A) => B) => (A) => C x => f(g(x)) end fn ``` ## Variable Length Argument Lists This feature is explicitly not supported by Ava. Lists should be used instead.