# Function Callbacks¶

For input file types that support functions, e.g., Lua, functions can also be read from the input file
into a `std::function`

, the wrapper for callables provided by the C++ standard library.

## Defining And Storing¶

This is accomplished by calling `addFunction`

on an Inlet or Container object.

Consider the following Lua function that accepts a vector in **R**^{2} or **R**^{3} and returns a double:

```
coef = function (v)
if v.dim == 2 then
return v.x + (v.y * 0.5)
else
return v.x + (v.y * 0.5) + (v.z * 0.25)
end
end
```

The schema for this function would be defined as follows:

```
schema
.addFunction("coef",
inlet::FunctionTag::Double,
{inlet::FunctionTag::Vector, inlet::FunctionTag::Double},
"The function representing the BC coefficient")
```

The return type and argument types are described with the `inlet::FunctionTag`

enumeration, which has the following members:

`Double`

- corresponds to a C++`double`

`String`

- corresponds to a C++`std::string`

`Vector`

- corresponds to a C++`inlet::InletVector`

`Void`

- corresponds to C++`void`

, should only be used for functions that don’t return a value

Note that a single type tag is passed for the return type, while a vector of tags is passed for the argument types. Currently a maximum of two arguments are supported. To declare a function with no arguments, simply leave the list of argument types empty.

Note

The `InletVector`

type (and its Lua representation) are statically-sized vectors with
a maximum dimension of three. That is, they can also be used to represent two-dimensional vectors.

In Lua, the following operations on the `Vector`

type are supported (for `Vector`

s `u`

, `v`

, and `w`

):

- Construction of a 3D vector:
`u = Vector.new(1, 2, 3)`

- Construction of a 2D vector:
`u = Vector.new(1, 2)`

- Construction of an empty vector (default dimension is 3):
`u = Vector.new()`

- Vector addition and subtraction:
`w = u + v`

,`w = u - v`

- Vector negation:
`v = -u`

- Scalar multiplication:
`v = u * 0.5`

,`v = 0.5 * u`

- Indexing (1-indexed for consistency with Lua):
`d = u[1]`

,`u[1] = 0.5`

- L2 norm and its square:
`d = u:norm()`

,`d = u:squared_norm()`

- Normalization:
`v = u:unitVector()`

- Dot and cross products:
`d = u:dot(v)`

,`w = u:cross(v)`

- Dimension retrieval:
`d = u.dim`

- Component retrieval:
`d = u.x`

,`d = u.y`

,`d = u.z`

## Accessing¶

To retrieve a function, both the implicit conversion and `get<T>`

syntax is supported. For example,
a function can be retrieved as follows:

```
// Retrieve the function (makes a copy) to be moved into the lambda
auto func =
base["coef"].get<std::function<double(FunctionType::Vector, double)>>();
```

It can also be assigned directly to a `std::function`

without the need to use `get<T>`

:

```
std::function<double(FunctionType::Vector)> coef = inlet["coef"];
```

Additionally, if a function does not need to be stored, the overhead of a copy can be eliminated by calling it directly:

```
double result = inlet["coef"].call<double>(axom::inlet::FunctionType::Vector{3, 5, 7});
```

Note

Using `call<ReturnType>(ArgType1, ArgType2, ...)`

requires both that the return type
be explicitly specified and that argument types be passed with the exact type as used in the
signature defined as part of the schema. This is because the arguments do not participate in
overload resolution.