# Functions Aside from built-in methods and functions, RCL supports user-defined functions. ```rcl let add = (x, y) => x + y; // Evaluates to 42. add(22, 20) ``` Functions are _first-class_: they are values that can be assigned to variables and passed to other functions. Functions are _anonymous_: the name you use to call them is not an inherent property of the function, but of the variable that it is assigned to. Functions are _closures_: the function body can reference variables defined outside of the body. Such functions are sometimes called _lambda functions_ or _lambdas_ in other languages. ## Defining functions A `=>` arrow creates a function, with the arguments on the left and the body on the right. ```rcl let sub = (x, y) => x - y; // Evaluates to 42. sub(50, 8) ``` A trailing comma in the argument list is optional. ```rcl let sub = ( x, y, ) => x - y; ``` When a function takes a single argument, the parentheses may be omitted. ```rcl let double_input = x => x * 2; ``` ## Closures A function can capture variables defined outside the function body. The names remain bound to the values they had when the function was defined. If a later let-binding shadows an earlier one, this does not affect the function. ```rcl let x = 42; let get_x = () => x; let x = 0; // Evaluates to 42, not to 0, because x was bound to 42 when get_x was defined. get_x() ``` Variables in RCL bind names to immutable values, not to mutable memory locations. This means that in a loop, functions capture the value that a variable has in that iteration of the loop. ```rcl let fs = [for k in [1, 2, 3]: x => x * k]; // Evaluates to [10, 20, 30]. [for f in fs: f(10)] ``` ## First-class functions Functions are values and can be passed to functions: ```rcl let apply_twice = (f, x) => f(f(x)); // Evaluates to 256 = (4 * 4) * (4 * 4); apply_twice(x => x * x, 4) ``` This is useful with built-in methods such as [`List.group_by`](type_list.md#group_by). ```rcl let replicants = [ { activation_year = 2016, name = "Pris Stratton" }, { activation_year = 2016, name = "Roy Batty" }, { activation_year = 2017, name = "Leon Kowalski" }, ]; replicants.group_by(r => r.activation_year) // Evaluates to: { 2016: [ { activation_year = 2016, name = "Pris Stratton" }, { activation_year = 2016, name = "Roy Batty" }, ], 2017: [ { activation_year = 2017, name = "Leon Kowalski" }, ], } ```