# AML Function > This document describes how to use AML Func to declare and reuse logic across an AML project :::caution AML Function cannot return models and datasets for now due to internal technical limitations. You can use [AML Extend](/reference/aml/extend) to reuse models and datasets instead. ::: ## Introduction An AML function is a reusable block of code designed to perform a specific task. It takes inputs (called parameters), processes them, and returns an output. ## Syntax ```tsx Func ( ((: )?( = )?)* ) (=> ) { } ``` * The return [type](/reference/aml/types) is optional as most of the time it can be inferred * The last expression will be returned as the output, there is no explicit `return` keyword * Parameters can declare default values using `= ` * Arguments can be passed positionally or by name (see Parameters and arguments below) ## Function declarations ```aml Func sum(x: Number, y: Number) { x + y } Func double(x: Number) { const multiple = 2 x * multiple } Func myvizBlockWithDataset(dataset: String) { // auto infer return type = VizBlock VizBlock { label: 'A pie chart' viz: PieChart { dataset: dataset // use the dataset parameter here instead of hard-coding legend: r(public_users.role) series { field { ref: r(public_users.id) aggregation: 'sum' } } } } } // equivalent to Func myvizBlockWithDataset(dataset: String) => VizBlock { // explicitly declare return type VizBlock { ... } } ``` ## Parameters and arguments ### Parameter types #### Required parameters Required parameters must be specified when calling the function and do not have default values. ```tsx Func chart( title: String, // Required data: Dataset // Required ) { /* Implementation */ } ``` #### Optional parameters Optional parameters have default values and can be omitted when calling the function. ```tsx Func sticky_note( content: RichText, color: Color = '#fff', // Optional with default size: Size = 'medium' // Optional with default ) { /* Implementation */ } ``` ### Parameter order rules - Required parameters must be placed before optional parameters - Optional parameters cannot appear before required parameters (invalid) ### Argument passing #### Positional arguments Arguments can be passed in the order parameters are defined: ```tsx sticky_note('Dashboard 1', '#eee', 'small') // All arguments specified sticky_note('Dashboard 2') // Using defaults for optional params ``` #### Named arguments Arguments can be specified by parameter name: ```tsx sticky_note( content='Dashboard', color='#eee', size='large' ) ``` ### Argument passing rules - Positional arguments must come before any named arguments - Once you start using named arguments, all subsequent arguments must also be named - Optional parameters can be omitted to use their default values - When skipping optional parameters in the middle, named arguments must be used for remaining parameters ### Examples #### Valid ```tsx // Assume this function signature for examples below: Func chart(title: String, data: Dataset, width: Number = 800, height: Number = 600) { /* ... */ } // All positional chart("Sales Report", salesData, 1000, 800) // Mix of positional and named chart("Sales Report", salesData, width=1000) // Skip optional param, use named for later param chart("Sales Report", salesData, height=800) // All named arguments chart( title="Sales Report", data=salesData, width=1000, height=800 ) ``` #### Invalid ```tsx // Named argument before positional chart("Sales Report", width=1000, salesData) // Wrong position for positional args chart(salesData, "Sales Report") ``` ## Calling functions A function will be executed when it is called: ```aml myvizBlockWithDataset('ecommerce') // return value /* VizBlock { label: 'A pie chart' viz: PieChart { dataset: 'ecommerce' legend: r(public_users.role) series { field { ref: r(public_users.id) aggregation: 'sum' } } } } */ ``` ## Function scope - Declaring a function creates a new scope. Variables and parameters declared inside a function are not accessible from outside it. However, a function can access all variables and functions defined in the scope where it was created. ```tsx Func sum_then_double(a: Number, b: Number) => Number { const factor = 2; (a + b) * factor } a // cannot refer to a here, as it is outside of the function scope b // ^ same c // ^ same ``` - Currently, AML allows for the nesting of functions and grants the inner function full access to all the variables and functions defined inside the outer function (and all other variables and functions that the outer function has access to) - However, the outer function does *not* have access to the variables and functions defined inside the inner function ```tsx Func sum_then_double(a: Number, b: Number) => Number { Func sum(a: Number, b: Number) { a + b // a, b is parameters of inner function sum } const factor = 2; sum(a, b) * factor // a, b is parameters of sum_then_double } sum_then_double(2, 3) // 10 ``` ## Combining with other features Functions can be combined with other AML features like [string interpolation](/reference/aml/string-interpolation) and [if-else](/reference/aml/if-else) to create powerful reusable templates: ```tsx Func greet(name: 'John' | 'Alice') { "Hello, ${if (name == 'John') { 'sir' } else { 'madam'} }!" } ``` ## See also - [Reusable components in Canvas Dashboard](/docs/canvas-dashboard/reusable-components) - [Build a Dashboard with Multiple Similar Charts](/docs/canvas-dashboard/build-similar-dashboards)