# Advanced Functions
This guide covers advanced function concepts in Razen, including higher-order functions, closures, and function composition.
## Higher-Order Functions
In Razen, functions are first-class citizens, which means they can be:
- Assigned to variables
- Passed as arguments to other functions
- Returned from other functions
### Functions as Arguments
You can pass functions as arguments to other functions:
```razen
// Define a function that takes another function as an argument
function applyTwice(func, value) {
return func(func(value))
}
// Define a simple function to double a number
function double(x) {
return x * 2
}
// Use applyTwice with the double function
let result = applyTwice(double, 3) // 12 (double applied twice: 3 → 6 → 12)
print(result)
```
### Returning Functions
Functions can also return other functions:
```razen
// Define a function that returns a function
function createMultiplier(factor) {
// Return a function that multiplies its argument by factor
return function(x) {
return x * factor
}
}
// Create a function that multiplies by 5
let multiplyByFive = createMultiplier(5)
// Use the created function
print(multiplyByFive(3)) // 15
print(multiplyByFive(10)) // 50
```
## Closures
A closure is a function that remembers the environment in which it was created, including any local variables that were in scope at the time:
```razen
function createCounter() {
let count = 0
return function() {
count += 1
return count
}
}
let counter = createCounter()
print(counter()) // 1
print(counter()) // 2
print(counter()) // 3
// Create a new counter
let counter2 = createCounter()
print(counter2()) // 1 (independent of the first counter)
```
In this example, each counter function maintains its own `count` variable, even though the `createCounter` function has finished executing.
## Function Composition
Function composition is the process of combining two or more functions to create a new function:
```razen
// Define two simple functions
function addOne(x) {
return x + 1
}
function double(x) {
return x * 2
}
// Compose these functions
function compose(f, g) {
return function(x) {
return f(g(x))
}
}
// Create a new function that doubles and then adds one
let doubleAndAddOne = compose(addOne, double)
print(doubleAndAddOne(3)) // 7 (double 3 to get 6, then add 1)
// Create a new function that adds one and then doubles
let addOneAndDouble = compose(double, addOne)
print(addOneAndDouble(3)) // 8 (add 1 to 3 to get 4, then double)
```
## Recursive Functions
Recursive functions are functions that call themselves:
```razen
// Calculate factorial using recursion
function factorial(n) {
if (n <= 1) {
return 1
} else {
return n * factorial(n - 1)
}
}
print(factorial(5)) // 120 (5 * 4 * 3 * 2 * 1)
```
## Function Currying
Currying is the technique of converting a function that takes multiple arguments into a sequence of functions that each take a single argument:
```razen
// A function that takes three arguments
function add(a, b, c) {
return a + b + c
}
// A curried version of the add function
function curriedAdd(a) {
return function(b) {
return function(c) {
return a + b + c
}
}
}
// Using the curried function
let result1 = curriedAdd(1)(2)(3) // 6
print(result1)
// Partial application
let addOne = curriedAdd(1)
let addOneAndTwo = addOne(2)
let result2 = addOneAndTwo(3) // 6
print(result2)
```
## Anonymous Functions (Lambdas)
Razen supports anonymous functions, also known as lambda functions:
```razen
// Using an anonymous function with map
let numbers = [1, 2, 3, 4, 5]
let doubled = map(numbers, function(x) { return x * 2 })
print(doubled) // [2, 4, 6, 8, 10]
// Shorter syntax for anonymous functions
let squared = map(numbers, x => x * x)
print(squared) // [1, 4, 9, 16, 25]
```
## Next Steps
Now that you've mastered advanced function concepts in Razen, explore [Object-Oriented Programming](/docs/advanced-topics/object-oriented.mdx) to learn about classes and objects in Razen.
# Advanced Functions
This guide covers advanced function concepts in Razen, including higher-order functions, closures, and function composition.
## Higher-Order Functions
In Razen, functions are first-class citizens, which means they can be:
- Assigned to variables
- Passed as arguments to other functions
- Returned from other functions
### Functions as Arguments
You can pass functions as arguments to other functions:
```razen
// Define a function that takes another function as an argument
function applyTwice(func, value) {
return func(func(value))
}
// Define a simple function to double a number
function double(x) {
return x * 2
}
// Use applyTwice with the double function
let result = applyTwice(double, 3) // 12 (double applied twice: 3 → 6 → 12)
print(result)
```
### Returning Functions
Functions can also return other functions:
```razen
// Define a function that returns a function
function createMultiplier(factor) {
// Return a function that multiplies its argument by factor
return function(x) {
return x * factor
}
}
// Create a function that multiplies by 5
let multiplyByFive = createMultiplier(5)
// Use the created function
print(multiplyByFive(3)) // 15
print(multiplyByFive(10)) // 50
```
## Closures
A closure is a function that remembers the environment in which it was created, including any local variables that were in scope at the time:
```razen
function createCounter() {
let count = 0
return function() {
count += 1
return count
}
}
let counter = createCounter()
print(counter()) // 1
print(counter()) // 2
print(counter()) // 3
// Create a new counter
let counter2 = createCounter()
print(counter2()) // 1 (independent of the first counter)
```
In this example, each counter function maintains its own `count` variable, even though the `createCounter` function has finished executing.
## Function Composition
Function composition is the process of combining two or more functions to create a new function:
```razen
// Define two simple functions
function addOne(x) {
return x + 1
}
function double(x) {
return x * 2
}
// Compose these functions
function compose(f, g) {
return function(x) {
return f(g(x))
}
}
// Create a new function that doubles and then adds one
let doubleAndAddOne = compose(addOne, double)
print(doubleAndAddOne(3)) // 7 (double 3 to get 6, then add 1)
// Create a new function that adds one and then doubles
let addOneAndDouble = compose(double, addOne)
print(addOneAndDouble(3)) // 8 (add 1 to 3 to get 4, then double)
```
## Recursive Functions
Recursive functions are functions that call themselves:
```razen
// Calculate factorial using recursion
function factorial(n) {
if (n <= 1) {
return 1
} else {
return n * factorial(n - 1)
}
}
print(factorial(5)) // 120 (5 * 4 * 3 * 2 * 1)
```
## Function Currying
Currying is the technique of converting a function that takes multiple arguments into a sequence of functions that each take a single argument:
```razen
// A function that takes three arguments
function add(a, b, c) {
return a + b + c
}
// A curried version of the add function
function curriedAdd(a) {
return function(b) {
return function(c) {
return a + b + c
}
}
}
// Using the curried function
let result1 = curriedAdd(1)(2)(3) // 6
print(result1)
// Partial application
let addOne = curriedAdd(1)
let addOneAndTwo = addOne(2)
let result2 = addOneAndTwo(3) // 6
print(result2)
```
## Anonymous Functions (Lambdas)
Razen supports anonymous functions, also known as lambda functions:
```razen
// Using an anonymous function with map
let numbers = [1, 2, 3, 4, 5]
let doubled = map(numbers, function(x) { return x * 2 })
print(doubled) // [2, 4, 6, 8, 10]
// Shorter syntax for anonymous functions
let squared = map(numbers, x => x * x)
print(squared) // [1, 4, 9, 16, 25]
```
## Next Steps
Now that you've mastered advanced function concepts in Razen, explore [Object-Oriented Programming](/docs/advanced-topics/object-oriented.mdx) to learn about classes and objects in Razen.