diff --git a/src/language/modules/MathModule.cpp b/src/language/modules/MathModule.cpp
index 7064dc33c1cc8eb0753edccb45ddae6ef988a2c5..e774284b385e7e74b8cb715f73b5ebec6f81b02e 100644
--- a/src/language/modules/MathModule.cpp
+++ b/src/language/modules/MathModule.cpp
@@ -4,78 +4,69 @@
 
 MathModule::MathModule()
 {
-  this->_addBuiltinFunction("sqrt", std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                                      std::function<double(double)>{[](double x) -> double { return std::sqrt(x); }}));
+  this->_addBuiltinFunction("sqrt", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                      [](double x) -> double { return std::sqrt(x); }));
 
-  this->_addBuiltinFunction("abs", std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                                     std::function<double(double)>{[](double x) -> double { return std::abs(x); }}));
+  this->_addBuiltinFunction("abs", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                     [](double x) -> double { return std::abs(x); }));
 
-  this->_addBuiltinFunction("sin", std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                                     std::function<double(double)>{[](double x) -> double { return std::sin(x); }}));
+  this->_addBuiltinFunction("sin", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                     [](double x) -> double { return std::sin(x); }));
 
-  this->_addBuiltinFunction("cos", std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                                     std::function<double(double)>{[](double x) -> double { return std::cos(x); }}));
+  this->_addBuiltinFunction("cos", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                     [](double x) -> double { return std::cos(x); }));
 
-  this->_addBuiltinFunction("tan", std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                                     std::function<double(double)>{[](double x) -> double { return std::tan(x); }}));
+  this->_addBuiltinFunction("tan", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                     [](double x) -> double { return std::tan(x); }));
 
-  this->_addBuiltinFunction("asin", std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                                      std::function<double(double)>{[](double x) -> double { return std::asin(x); }}));
+  this->_addBuiltinFunction("asin", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                      [](double x) -> double { return std::asin(x); }));
 
-  this->_addBuiltinFunction("acos", std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                                      std::function<double(double)>{[](double x) -> double { return std::acos(x); }}));
+  this->_addBuiltinFunction("acos", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                      [](double x) -> double { return std::acos(x); }));
 
-  this->_addBuiltinFunction("atan", std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                                      std::function<double(double)>{[](double x) -> double { return std::atan(x); }}));
+  this->_addBuiltinFunction("atan", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                      [](double x) -> double { return std::atan(x); }));
 
-  this->_addBuiltinFunction("atan2", std::make_shared<BuiltinFunctionEmbedder<double, double, double>>(
-                                       std::function<double(double, double)>{
-                                         [](double x, double y) -> double { return std::atan2(x, y); }}));
+  this->_addBuiltinFunction("atan2", std::make_shared<BuiltinFunctionEmbedder<double(double, double)>>(
+                                       [](double x, double y) -> double { return std::atan2(x, y); }));
 
-  this->_addBuiltinFunction("sinh", std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                                      std::function<double(double)>{[](double x) -> double { return std::sinh(x); }}));
+  this->_addBuiltinFunction("sinh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                      [](double x) -> double { return std::sinh(x); }));
 
-  this->_addBuiltinFunction("cosh", std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                                      std::function<double(double)>{[](double x) -> double { return std::cosh(x); }}));
+  this->_addBuiltinFunction("cosh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                      [](double x) -> double { return std::cosh(x); }));
 
-  this->_addBuiltinFunction("tanh", std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                                      std::function<double(double)>{[](double x) -> double { return std::tanh(x); }}));
+  this->_addBuiltinFunction("tanh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                      [](double x) -> double { return std::tanh(x); }));
 
-  this->_addBuiltinFunction("asinh",
-                            std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                              std::function<double(double)>{[](double x) -> double { return std::asinh(x); }}));
+  this->_addBuiltinFunction("asinh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                       [](double x) -> double { return std::asinh(x); }));
 
-  this->_addBuiltinFunction("acosh",
-                            std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                              std::function<double(double)>{[](double x) -> double { return std::acosh(x); }}));
+  this->_addBuiltinFunction("acosh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                       [](double x) -> double { return std::acosh(x); }));
 
-  this->_addBuiltinFunction("atanh",
-                            std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                              std::function<double(double)>{[](double x) -> double { return std::atanh(x); }}));
+  this->_addBuiltinFunction("atanh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                       [](double x) -> double { return std::atanh(x); }));
 
-  this->_addBuiltinFunction("exp", std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                                     std::function<double(double)>{[](double x) -> double { return std::exp(x); }}));
+  this->_addBuiltinFunction("exp", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                     [](double x) -> double { return std::exp(x); }));
 
-  this->_addBuiltinFunction("log", std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                                     std::function<double(double)>{[](double x) -> double { return std::log(x); }}));
+  this->_addBuiltinFunction("log", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                     [](double x) -> double { return std::log(x); }));
 
-  this->_addBuiltinFunction("pow", std::make_shared<BuiltinFunctionEmbedder<double, double, double>>(
-                                     std::function<double(double, double)>{
-                                       [](double x, double y) -> double { return std::pow(x, y); }}));
+  this->_addBuiltinFunction("pow", std::make_shared<BuiltinFunctionEmbedder<double(double, double)>>(
+                                     [](double x, double y) -> double { return std::pow(x, y); }));
 
-  this->_addBuiltinFunction("ceil",
-                            std::make_shared<BuiltinFunctionEmbedder<int64_t, double>>(
-                              std::function<int64_t(double)>{[](double x) -> int64_t { return std::ceil(x); }}));
+  this->_addBuiltinFunction("ceil", std::make_shared<BuiltinFunctionEmbedder<int64_t(double)>>(
+                                      [](double x) -> int64_t { return std::ceil(x); }));
 
-  this->_addBuiltinFunction("floor",
-                            std::make_shared<BuiltinFunctionEmbedder<int64_t, double>>(
-                              std::function<int64_t(double)>{[](double x) -> int64_t { return std::floor(x); }}));
+  this->_addBuiltinFunction("floor", std::make_shared<BuiltinFunctionEmbedder<int64_t(double)>>(
+                                       [](double x) -> int64_t { return std::floor(x); }));
 
-  this->_addBuiltinFunction("trunc",
-                            std::make_shared<BuiltinFunctionEmbedder<int64_t, double>>(
-                              std::function<int64_t(double)>{[](double x) -> int64_t { return std::trunc(x); }}));
+  this->_addBuiltinFunction("trunc", std::make_shared<BuiltinFunctionEmbedder<int64_t(double)>>(
+                                       [](double x) -> int64_t { return std::trunc(x); }));
 
-  this->_addBuiltinFunction("round",
-                            std::make_shared<BuiltinFunctionEmbedder<int64_t, double>>(
-                              std::function<int64_t(double)>{[](double x) -> int64_t { return std::lround(x); }}));
+  this->_addBuiltinFunction("round", std::make_shared<BuiltinFunctionEmbedder<int64_t(double)>>(
+                                       [](double x) -> int64_t { return std::lround(x); }));
 }
diff --git a/src/language/modules/MeshModule.cpp b/src/language/modules/MeshModule.cpp
index 0236d8d7995bedb254062d6dd29f26bd064b04b1..8394d940dfd774f58fcd7a16f54c91e0eb5334ea 100644
--- a/src/language/modules/MeshModule.cpp
+++ b/src/language/modules/MeshModule.cpp
@@ -64,21 +64,18 @@ MeshModule::MeshModule()
   this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IMesh>>);
 
   this->_addBuiltinFunction("readGmsh",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>, std::string>>(
-                              std::function<std::shared_ptr<const IMesh>(std::string)>{
+                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>(const std::string&)>>(
 
-                                [](const std::string& file_name) -> std::shared_ptr<const IMesh> {
-                                  GmshReader gmsh_reader(file_name);
-                                  return gmsh_reader.mesh();
-                                }}
+                              [](const std::string& file_name) -> std::shared_ptr<const IMesh> {
+                                GmshReader gmsh_reader(file_name);
+                                return gmsh_reader.mesh();
+                              }
 
                               ));
 
-  this
-    ->_addBuiltinFunction("transform",
-                          std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>,
-                                                                   std::shared_ptr<const IMesh>, FunctionSymbolId>>(
-                            std::function<std::shared_ptr<const IMesh>(std::shared_ptr<const IMesh>, FunctionSymbolId)>{
+  this->_addBuiltinFunction("transform",
+                            std::make_shared<BuiltinFunctionEmbedder<
+                              std::shared_ptr<const IMesh>(std::shared_ptr<const IMesh>, const FunctionSymbolId&)>>(
 
                               [](std::shared_ptr<const IMesh> p_mesh,
                                  const FunctionSymbolId& function_id) -> std::shared_ptr<const IMesh> {
@@ -99,97 +96,88 @@ MeshModule::MeshModule()
                                   throw UnexpectedError("invalid mesh dimension");
                                 }
                                 }
-                              }}
+                              }
 
-                            ));
+                              ));
 
   this->_addBuiltinFunction("cartesian1dMesh",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>, TinyVector<1>,
-                                                                     TinyVector<1>, std::vector<uint64_t>>>(
+                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
+                              const IMesh>(const TinyVector<1>, const TinyVector<1>, const std::vector<uint64_t>&)>>(
 
-                              std::function<std::shared_ptr<const IMesh>(TinyVector<1>, TinyVector<1>,
-                                                                         std::vector<uint64_t>)>{
+                              [&](const TinyVector<1> a, const TinyVector<1> b,
+                                  const std::vector<uint64_t>& box_sizes) -> std::shared_ptr<const IMesh> {
+                                constexpr uint64_t dimension = 1;
 
-                                [&](const TinyVector<1> a, const TinyVector<1> b,
-                                    const std::vector<uint64_t>& box_sizes) -> std::shared_ptr<const IMesh> {
-                                  constexpr uint64_t dimension = 1;
+                                if (box_sizes.size() != dimension) {
+                                  throw NormalError("expecting " + std::to_string(dimension) +
+                                                    " dimensions, provided " + std::to_string(box_sizes.size()));
+                                }
 
-                                  if (box_sizes.size() != dimension) {
-                                    throw NormalError("expecting " + std::to_string(dimension) +
-                                                      " dimensions, provided " + std::to_string(box_sizes.size()));
+                                const TinyVector<dimension, uint64_t> sizes = [&]() {
+                                  TinyVector<dimension, uint64_t> s;
+                                  for (size_t i = 0; i < dimension; ++i) {
+                                    s[i] = box_sizes[i];
                                   }
+                                  return s;
+                                }();
 
-                                  const TinyVector<dimension, uint64_t> sizes = [&]() {
-                                    TinyVector<dimension, uint64_t> s;
-                                    for (size_t i = 0; i < dimension; ++i) {
-                                      s[i] = box_sizes[i];
-                                    }
-                                    return s;
-                                  }();
-
-                                  CartesianMeshBuilder builder{a, b, sizes};
-                                  return builder.mesh();
-                                }}
+                                CartesianMeshBuilder builder{a, b, sizes};
+                                return builder.mesh();
+                              }
 
                               ));
 
   this->_addBuiltinFunction("cartesian2dMesh",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>, TinyVector<2>,
-                                                                     TinyVector<2>, std::vector<uint64_t>>>(
+                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
+                              const IMesh>(const TinyVector<2>, const TinyVector<2>, const std::vector<uint64_t>&)>>(
 
-                              std::function<std::shared_ptr<const IMesh>(TinyVector<2>, TinyVector<2>,
-                                                                         std::vector<uint64_t>)>{
+                              [&](const TinyVector<2> a, const TinyVector<2> b,
+                                  const std::vector<uint64_t>& box_sizes) -> std::shared_ptr<const IMesh> {
+                                constexpr uint64_t dimension = 2;
 
-                                [&](const TinyVector<2> a, const TinyVector<2> b,
-                                    const std::vector<uint64_t>& box_sizes) -> std::shared_ptr<const IMesh> {
-                                  constexpr uint64_t dimension = 2;
+                                if (box_sizes.size() != dimension) {
+                                  throw NormalError("expecting " + std::to_string(dimension) +
+                                                    " dimensions, provided " + std::to_string(box_sizes.size()));
+                                }
 
-                                  if (box_sizes.size() != dimension) {
-                                    throw NormalError("expecting " + std::to_string(dimension) +
-                                                      " dimensions, provided " + std::to_string(box_sizes.size()));
+                                const TinyVector<dimension, uint64_t> sizes = [&]() {
+                                  TinyVector<dimension, uint64_t> s;
+                                  for (size_t i = 0; i < dimension; ++i) {
+                                    s[i] = box_sizes[i];
                                   }
+                                  return s;
+                                }();
 
-                                  const TinyVector<dimension, uint64_t> sizes = [&]() {
-                                    TinyVector<dimension, uint64_t> s;
-                                    for (size_t i = 0; i < dimension; ++i) {
-                                      s[i] = box_sizes[i];
-                                    }
-                                    return s;
-                                  }();
-
-                                  CartesianMeshBuilder builder{a, b, sizes};
-                                  return builder.mesh();
-                                }}
+                                CartesianMeshBuilder builder{a, b, sizes};
+                                return builder.mesh();
+                              }
 
                               ));
 
   this->_addBuiltinFunction("cartesian3dMesh",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>, TinyVector<3>,
-                                                                     TinyVector<3>, std::vector<uint64_t>>>(
+                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
+                              const IMesh>(const TinyVector<3>&, const TinyVector<3>&, const std::vector<uint64_t>&)>>(
 
-                              std::function<std::shared_ptr<const IMesh>(TinyVector<3>, TinyVector<3>,
-                                                                         std::vector<uint64_t>)>{
+                              [&](const TinyVector<3>& a, const TinyVector<3>& b,
+                                  const std::vector<uint64_t>& box_sizes) -> std::shared_ptr<const IMesh> {
+                                constexpr uint64_t dimension = 3;
 
-                                [&](const TinyVector<3>& a, const TinyVector<3>& b,
-                                    const std::vector<uint64_t>& box_sizes) -> std::shared_ptr<const IMesh> {
-                                  constexpr uint64_t dimension = 3;
+                                if (box_sizes.size() != dimension) {
+                                  throw NormalError("expecting " + std::to_string(dimension) +
+                                                    " dimensions, provided " + std::to_string(box_sizes.size()));
+                                }
 
-                                  if (box_sizes.size() != dimension) {
-                                    throw NormalError("expecting " + std::to_string(dimension) +
-                                                      " dimensions, provided " + std::to_string(box_sizes.size()));
+                                const TinyVector<dimension, uint64_t> sizes = [&]() {
+                                  TinyVector<dimension, uint64_t> s;
+                                  for (size_t i = 0; i < dimension; ++i) {
+                                    s[i] = box_sizes[i];
                                   }
+                                  return s;
+                                }();
 
-                                  const TinyVector<dimension, uint64_t> sizes = [&]() {
-                                    TinyVector<dimension, uint64_t> s;
-                                    for (size_t i = 0; i < dimension; ++i) {
-                                      s[i] = box_sizes[i];
-                                    }
-                                    return s;
-                                  }();
-
-                                  CartesianMeshBuilder builder{a, b, sizes};
-                                  return builder.mesh();
-                                }}
+                                CartesianMeshBuilder builder{a, b, sizes};
+                                return builder.mesh();
+                              }
 
                               ));
 }
diff --git a/src/language/modules/SchemeModule.cpp b/src/language/modules/SchemeModule.cpp
index fc9eae90669693c784f204744e93f0d61c3be119..a1fedff2f0168da1d2fe58c97a5bfc91cd6d4154 100644
--- a/src/language/modules/SchemeModule.cpp
+++ b/src/language/modules/SchemeModule.cpp
@@ -208,72 +208,65 @@ SchemeModule::SchemeModule()
 
   this->_addBuiltinFunction("boundaryName",
                             std::make_shared<
-                              BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryDescriptor>, std::string>>(
-                              std::function<std::shared_ptr<const IBoundaryDescriptor>(std::string)>{
+                              BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryDescriptor>(const std::string&)>>(
 
-                                [](const std::string& boundary_name) -> std::shared_ptr<const IBoundaryDescriptor> {
-                                  return std::make_shared<NamedBoundaryDescriptor>(boundary_name);
-                                }}
+                              [](const std::string& boundary_name) -> std::shared_ptr<const IBoundaryDescriptor> {
+                                return std::make_shared<NamedBoundaryDescriptor>(boundary_name);
+                              }
 
                               ));
 
   this->_addBuiltinFunction("boundaryTag",
                             std::make_shared<
-                              BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryDescriptor>, int64_t>>(
-                              std::function<std::shared_ptr<const IBoundaryDescriptor>(int64_t)>{
+                              BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryDescriptor>(int64_t)>>(
 
-                                [](int64_t boundary_tag) -> std::shared_ptr<const IBoundaryDescriptor> {
-                                  return std::make_shared<NumberedBoundaryDescriptor>(boundary_tag);
-                                }}
+                              [](int64_t boundary_tag) -> std::shared_ptr<const IBoundaryDescriptor> {
+                                return std::make_shared<NumberedBoundaryDescriptor>(boundary_tag);
+                              }
 
                               ));
 
   this
     ->_addBuiltinFunction("symmetry",
-                          std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryConditionDescriptor>,
-                                                                   std::shared_ptr<const IBoundaryDescriptor>>>(
-                            std::function<std::shared_ptr<const IBoundaryConditionDescriptor>(
-                              std::shared_ptr<const IBoundaryDescriptor>)>{
+                          std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryConditionDescriptor>(
+                            std::shared_ptr<const IBoundaryDescriptor>)>>(
 
-                              [](std::shared_ptr<const IBoundaryDescriptor> boundary)
-                                -> std::shared_ptr<const IBoundaryConditionDescriptor> {
-                                return std::make_shared<SymmetryBoundaryConditionDescriptor>(boundary);
-                              }}
+                            [](std::shared_ptr<const IBoundaryDescriptor> boundary)
+                              -> std::shared_ptr<const IBoundaryConditionDescriptor> {
+                              return std::make_shared<SymmetryBoundaryConditionDescriptor>(boundary);
+                            }
 
                             ));
 
   this->_addBuiltinFunction("glace",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<void, std::shared_ptr<const IMesh>,
-                                                      std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>,
-                                                      FunctionSymbolId, FunctionSymbolId, FunctionSymbolId>>(
-                              std::function<void(std::shared_ptr<const IMesh>,
-                                                 std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>,
-                                                 FunctionSymbolId, FunctionSymbolId, FunctionSymbolId)>{
-
-                                [](std::shared_ptr<const IMesh> p_mesh,
-                                   const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&
-                                     bc_descriptor_list,
-                                   const FunctionSymbolId& rho_id, const FunctionSymbolId& u_id,
-                                   const FunctionSymbolId& p_id) -> void {
-                                  switch (p_mesh->dimension()) {
-                                  case 1: {
-                                    GlaceScheme<1>{*p_mesh, bc_descriptor_list, rho_id, u_id, p_id};
-                                    break;
-                                  }
-                                  case 2: {
-                                    GlaceScheme<2>{*p_mesh, bc_descriptor_list, rho_id, u_id, p_id};
-                                    break;
-                                  }
-                                  case 3: {
-                                    GlaceScheme<3>{*p_mesh, bc_descriptor_list, rho_id, u_id, p_id};
-                                    break;
-                                  }
-                                  default: {
-                                    throw UnexpectedError("invalid mesh dimension");
-                                  }
-                                  }
+                            std::make_shared<BuiltinFunctionEmbedder<
+                              void(std::shared_ptr<const IMesh>,
+                                   const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&,
+                                   const FunctionSymbolId&, const FunctionSymbolId&, const FunctionSymbolId&)>>(
+
+                              [](std::shared_ptr<const IMesh> p_mesh,
+                                 const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&
+                                   bc_descriptor_list,
+                                 const FunctionSymbolId& rho_id, const FunctionSymbolId& u_id,
+                                 const FunctionSymbolId& p_id) -> void {
+                                switch (p_mesh->dimension()) {
+                                case 1: {
+                                  GlaceScheme<1>{*p_mesh, bc_descriptor_list, rho_id, u_id, p_id};
+                                  break;
+                                }
+                                case 2: {
+                                  GlaceScheme<2>{*p_mesh, bc_descriptor_list, rho_id, u_id, p_id};
+                                  break;
+                                }
+                                case 3: {
+                                  GlaceScheme<3>{*p_mesh, bc_descriptor_list, rho_id, u_id, p_id};
+                                  break;
                                 }
+                                default: {
+                                  throw UnexpectedError("invalid mesh dimension");
+                                }
+                                }
+                              }
 
-                              }));
+                              ));
 }
diff --git a/src/language/modules/VTKModule.cpp b/src/language/modules/VTKModule.cpp
index aafe8d2abbe0a8167e96e686ffc54e7184645585..30d2c11e48b580622ae24e30c9d71bb2d46b007d 100644
--- a/src/language/modules/VTKModule.cpp
+++ b/src/language/modules/VTKModule.cpp
@@ -10,40 +10,40 @@
 VTKModule::VTKModule()
 {
   this->_addBuiltinFunction("writeVTK",
-                            std::make_shared<BuiltinFunctionEmbedder<void, std::shared_ptr<const IMesh>, std::string>>(
-                              std::function<void(std::shared_ptr<const IMesh>, std::string)>{
-
-                                [](std::shared_ptr<const IMesh> p_mesh, const std::string& filename) -> void {
-                                  VTKWriter writer(filename, 0.1);
-
-                                  static double time = 0;
-
-                                  switch (p_mesh->dimension()) {
-                                  case 1: {
-                                    using MeshType       = Mesh<Connectivity<1>>;
-                                    const MeshType& mesh = dynamic_cast<const MeshType&>(*p_mesh);
-
-                                    writer.write(mesh, OutputNamedItemValueSet{}, time, true);
-                                    break;
-                                  }
-                                  case 2: {
-                                    using MeshType       = Mesh<Connectivity<2>>;
-                                    const MeshType& mesh = dynamic_cast<const MeshType&>(*p_mesh);
-
-                                    writer.write(mesh, OutputNamedItemValueSet{}, time, true);
-                                    break;
-                                  }
-                                  case 3: {
-                                    using MeshType       = Mesh<Connectivity<3>>;
-                                    const MeshType& mesh = dynamic_cast<const MeshType&>(*p_mesh);
-
-                                    writer.write(mesh, OutputNamedItemValueSet{}, time, true);
-                                    break;
-                                  }
-                                  }
-
-                                  time++;
+                            std::make_shared<
+                              BuiltinFunctionEmbedder<void(std::shared_ptr<const IMesh>, const std::string&)>>(
+
+                              [](std::shared_ptr<const IMesh> p_mesh, const std::string& filename) -> void {
+                                VTKWriter writer(filename, 0.1);
+
+                                static double time = 0;
+
+                                switch (p_mesh->dimension()) {
+                                case 1: {
+                                  using MeshType       = Mesh<Connectivity<1>>;
+                                  const MeshType& mesh = dynamic_cast<const MeshType&>(*p_mesh);
+
+                                  writer.write(mesh, OutputNamedItemValueSet{}, time, true);
+                                  break;
+                                }
+                                case 2: {
+                                  using MeshType       = Mesh<Connectivity<2>>;
+                                  const MeshType& mesh = dynamic_cast<const MeshType&>(*p_mesh);
+
+                                  writer.write(mesh, OutputNamedItemValueSet{}, time, true);
+                                  break;
+                                }
+                                case 3: {
+                                  using MeshType       = Mesh<Connectivity<3>>;
+                                  const MeshType& mesh = dynamic_cast<const MeshType&>(*p_mesh);
+
+                                  writer.write(mesh, OutputNamedItemValueSet{}, time, true);
+                                  break;
                                 }
+                                }
+
+                                time++;
+                              }
 
-                              }));
+                              ));
 }
diff --git a/src/language/utils/BuiltinFunctionEmbedder.hpp b/src/language/utils/BuiltinFunctionEmbedder.hpp
index 9a77fec82e6bfa3b9496a2e600144d014753f67c..4870ab0028bc1c1bc82f13b7b4b20d5d989ecce9 100644
--- a/src/language/utils/BuiltinFunctionEmbedder.hpp
+++ b/src/language/utils/BuiltinFunctionEmbedder.hpp
@@ -34,11 +34,22 @@ class IBuiltinFunctionEmbedder
 };
 
 template <typename FX, typename... Args>
-class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder
+class BuiltinFunctionEmbedder
+{
+  static_assert(std::is_class_v<BuiltinFunctionEmbedder<FX, Args...>>,
+                "wrong template parameters do not use <FX, Args...>, use <FX(Args...)>");
+};
+
+template <typename T>
+inline constexpr bool is_const_ref_or_non_ref = (std::is_const_v<T> and std::is_lvalue_reference_v<T>) or
+                                                (not std::is_lvalue_reference_v<T>);
+
+template <typename FX, typename... Args>
+class BuiltinFunctionEmbedder<FX(Args...)> : public IBuiltinFunctionEmbedder
 {
  private:
   std::function<FX(Args...)> m_f;
-  using ArgsTuple = std::tuple<Args...>;
+  using ArgsTuple = std::tuple<std::decay_t<Args>...>;
 
   template <size_t I>
   PUGS_INLINE void
@@ -56,8 +67,15 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder
           std::get<I>(t) = v_i;
         } else if constexpr (is_shared_ptr_v<Ti_Type>) {
           if constexpr (std::is_same_v<Vi_Type, EmbeddedData>) {
-            auto& data_handler = static_cast<const DataHandler<typename Ti_Type::element_type>&>(v_i.get());
-            std::get<I>(t)     = data_handler.data_ptr();
+            using Ti_handeled_type = typename Ti_Type::element_type;
+            try {
+              auto& data_handler = dynamic_cast<const DataHandler<Ti_handeled_type>&>(v_i.get());
+              std::get<I>(t)     = data_handler.data_ptr();
+            }
+            catch (std::bad_cast&) {
+              throw UnexpectedError("unexpected argument types while casting: invalid EmbeddedData type, expecting " +
+                                    demangle<DataHandler<Ti_handeled_type>>());
+            }
           } else {
             throw UnexpectedError("unexpected argument types while casting: expecting EmbeddedData");
           }
@@ -70,20 +88,27 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder
               using Ti_handeled_type = typename Ti_value_type::element_type;
               std::get<I>(t).resize(v_i.size());
               for (size_t j = 0; j < v_i.size(); ++j) {
-                auto& data_handler = dynamic_cast<const DataHandler<Ti_handeled_type>&>(v_i[j].get());
-                std::get<I>(t)[j]  = data_handler.data_ptr();
+                try {
+                  auto& data_handler = dynamic_cast<const DataHandler<Ti_handeled_type>&>(v_i[j].get());
+                  std::get<I>(t)[j]  = data_handler.data_ptr();
+                }
+                catch (std::bad_cast&) {
+                  throw UnexpectedError(
+                    "unexpected argument types while casting: invalid EmbeddedData type, expecting " +
+                    demangle<DataHandler<Ti_handeled_type>>());
+                }
               }
             } else {
-              throw UnexpectedError("Unexpected argument types while casting " + demangle<Vi_Type>() + " -> " +
-                                    demangle<Ti_Type>());
+              throw UnexpectedError("unexpected argument types while casting \"" + demangle<Vi_Type>() + "\" to \"" +
+                                    demangle<Ti_Type>() + '"');
             }
           } else {
-            throw UnexpectedError("Unexpected argument types while casting " + demangle<Vi_Type>() + " -> " +
-                                  demangle<Ti_Type>());
+            throw UnexpectedError("unexpected argument types while casting \"" + demangle<Vi_Type>() + "\" to \"" +
+                                  demangle<Ti_Type>() + '"');
           }
         } else {
-          throw UnexpectedError("Unexpected argument types while casting " + demangle<Vi_Type>() + " -> " +
-                                demangle<Ti_Type>());
+          throw UnexpectedError("unexpected argument types while casting \"" + demangle<Vi_Type>() + "\" to \"" +
+                                demangle<Ti_Type>() + '"');
         }
       },
       v[I]);
@@ -101,7 +126,14 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder
   PUGS_INLINE ASTNodeDataType
   _getOneParameterDataType(ArgsTuple& t) const
   {
-    return ast_node_data_type_from<std::decay_t<decltype(std::get<I>(t))>>;
+    using ArgN_T = std::decay_t<decltype(std::get<I>(t))>;
+    if constexpr (is_data_variant_v<ArgN_T>) {
+      return ast_node_data_type_from<ArgN_T>;
+    } else if constexpr (std::is_same_v<void, ArgN_T>) {
+      return ASTNodeDataType::void_t;
+    } else {
+      return ASTNodeDataType::type_id_t;
+    }
   }
 
   template <size_t... I>
@@ -113,11 +145,45 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder
     return parameter_type_list;
   }
 
+  template <typename T>
+  PUGS_INLINE std::shared_ptr<IDataHandler>
+  _createHandler(std::shared_ptr<T> data) const
+  {
+    return std::make_shared<DataHandler<T>>(data);
+  }
+
+  template <size_t I>
+  PUGS_INLINE void constexpr _check_arg() const
+  {
+    using ArgN_T = std::tuple_element_t<I, std::tuple<Args...>>;
+    if constexpr (std::is_lvalue_reference_v<ArgN_T>) {
+      static_assert(std::is_const_v<std::remove_reference_t<ArgN_T>>,
+                    "builtin function arguments are non mutable use 'const' when passing references");
+    }
+
+    if constexpr (is_std_ptr_v<ArgN_T>) {
+      static_assert(std::is_const_v<typename ArgN_T::element_type>,
+                    "builtin function arguments are non mutable. For instance use std::shared_ptr<const T>");
+    }
+  }
+
+  template <size_t... I>
+  PUGS_INLINE void constexpr _check_arg_list(std::index_sequence<I...>) const
+  {
+    (_check_arg<I>(), ...);
+  }
+
  public:
   PUGS_INLINE ASTNodeDataType
   getReturnDataType() const final
   {
-    return ast_node_data_type_from<FX>;
+    if constexpr (is_data_variant_v<FX>) {
+      return ast_node_data_type_from<FX>;
+    } else if constexpr (std::is_same_v<void, FX>) {
+      return ASTNodeDataType::void_t;
+    } else {
+      return ASTNodeDataType::type_id_t;
+    }
   }
 
   PUGS_INLINE std::vector<ASTNodeDataType>
@@ -136,14 +202,6 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder
     return sizeof...(Args);
   }
 
- private:
-  template <typename T>
-  PUGS_INLINE std::shared_ptr<IDataHandler>
-  _createHandler(std::shared_ptr<T> data) const
-  {
-    return std::make_shared<DataHandler<T>>(data);
-  }
-
  public:
   PUGS_INLINE
   DataVariant
@@ -154,7 +212,7 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder
     using IndexSequence = std::make_index_sequence<N>;
 
     this->_copyFromVector(t, x, IndexSequence{});
-    if constexpr (std::is_arithmetic_v<FX>) {
+    if constexpr (is_data_variant_v<FX>) {
       return {std::apply(m_f, t)};
     } else if constexpr (std::is_same_v<FX, void>) {
       std::apply(m_f, t);
@@ -164,27 +222,51 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder
     }
   }
 
-  template <typename FX2, typename... Args2>
-  BuiltinFunctionEmbedder(std::function<FX2(Args2...)> f) : m_f{f}
+  BuiltinFunctionEmbedder(std::function<FX(Args...)> f) : m_f{f}
   {
-    static_assert(std::is_same_v<FX, FX2>, "incorrect return type");
-    static_assert(sizeof...(Args) == sizeof...(Args2), "invalid number of arguments");
-    using Args2Tuple = std::tuple<Args2...>;
-    static_assert(std::is_same_v<ArgsTuple, Args2Tuple>, "invalid arguments type");
+    using IndexSequence = std::make_index_sequence<std::tuple_size_v<ArgsTuple>>;
+    this->_check_arg_list(IndexSequence{});
+
+    static_assert((std::is_same_v<Args, Args> and ...));
   }
+
+  BuiltinFunctionEmbedder(const BuiltinFunctionEmbedder&) = delete;
+  BuiltinFunctionEmbedder(BuiltinFunctionEmbedder&&)      = delete;
+
+  ~BuiltinFunctionEmbedder() = default;
+};
+
+template <typename FX>
+class BuiltinFunctionEmbedder<FX, void>
+{
+  static_assert(std::is_class_v<BuiltinFunctionEmbedder<FX, void>>,
+                "wrong template parameters do not use <FX, void>, use <FX(void)>");
 };
 
 template <typename FX>
-class BuiltinFunctionEmbedder<FX, void> : public IBuiltinFunctionEmbedder
+class BuiltinFunctionEmbedder<FX(void)> : public IBuiltinFunctionEmbedder
 {
  private:
   std::function<FX(void)> m_f;
 
+  template <typename T>
+  PUGS_INLINE std::shared_ptr<IDataHandler>
+  _createHandler(std::shared_ptr<T> data) const
+  {
+    return std::make_shared<DataHandler<T>>(data);
+  }
+
  public:
   PUGS_INLINE ASTNodeDataType
   getReturnDataType() const final
   {
-    return ast_node_data_type_from<FX>;
+    if constexpr (is_data_variant_v<FX>) {
+      return ast_node_data_type_from<FX>;
+    } else if constexpr (std::is_same_v<void, FX>) {
+      return ASTNodeDataType::void_t;
+    } else {
+      return ASTNodeDataType::type_id_t;
+    }
   }
 
   PUGS_INLINE std::vector<ASTNodeDataType>
@@ -199,12 +281,11 @@ class BuiltinFunctionEmbedder<FX, void> : public IBuiltinFunctionEmbedder
     return 0;
   }
 
- public:
   PUGS_INLINE
   DataVariant
   apply(const std::vector<DataVariant>&) const final
   {
-    if constexpr (std::is_arithmetic_v<FX>) {
+    if constexpr (is_data_variant_v<FX>) {
       return {m_f()};
     } else if constexpr (std::is_same_v<FX, void>) {
       m_f();
@@ -214,7 +295,12 @@ class BuiltinFunctionEmbedder<FX, void> : public IBuiltinFunctionEmbedder
     }
   }
 
-  BuiltinFunctionEmbedder(const std::function<void(void)>& f) : m_f{f} {}
+  BuiltinFunctionEmbedder(std::function<FX(void)> f) : m_f{f} {}
+
+  BuiltinFunctionEmbedder(const BuiltinFunctionEmbedder&) = delete;
+  BuiltinFunctionEmbedder(BuiltinFunctionEmbedder&&)      = delete;
+
+  ~BuiltinFunctionEmbedder() = default;
 };
 
 #endif   //  BUILTIN_FUNCTION_EMBEDDER_HPP
diff --git a/src/language/utils/DataVariant.hpp b/src/language/utils/DataVariant.hpp
index b8d45704d08e4a8c3d6f91b22e7d3f34c5f6964f..13744172a73c2e3c54d97412cd654ae7211ad42c 100644
--- a/src/language/utils/DataVariant.hpp
+++ b/src/language/utils/DataVariant.hpp
@@ -4,6 +4,7 @@
 #include <algebra/TinyVector.hpp>
 #include <language/utils/EmbeddedData.hpp>
 #include <language/utils/FunctionSymbolId.hpp>
+#include <utils/PugsTraits.hpp>
 
 #include <iostream>
 #include <tuple>
@@ -34,6 +35,9 @@ using DataVariant = std::variant<std::monostate,
                                  AggregateDataVariant,
                                  FunctionSymbolId>;
 
+template <typename T, typename...>
+inline constexpr bool is_data_variant_v = is_variant<T, DataVariant>::value;
+
 std::ostream& operator<<(std::ostream& os, const DataVariant& v);
 
 class AggregateDataVariant   // LCOV_EXCL_LINE
diff --git a/src/utils/PugsTraits.hpp b/src/utils/PugsTraits.hpp
index cb934a2ab2cf1e4d563a8703b4751d3799a753ae..52acae2bb0c80aecab29fb125604b7b869fc5f3c 100644
--- a/src/utils/PugsTraits.hpp
+++ b/src/utils/PugsTraits.hpp
@@ -4,6 +4,7 @@
 #include <cstddef>
 #include <memory>
 #include <type_traits>
+#include <variant>
 #include <vector>
 
 template <size_t N, typename T>
@@ -83,4 +84,15 @@ inline constexpr bool is_tiny_vector_v = false;
 template <size_t N, typename T>
 inline constexpr bool is_tiny_vector_v<TinyVector<N, T>> = true;
 
+// Traits is_tiny_vector
+// helper to check if a type is part of a variant
+
+template <typename T, typename V>
+struct is_variant;
+
+template <typename T, typename... ALL_T>
+struct is_variant<T, std::variant<ALL_T...>> : public std::disjunction<std::is_same<T, ALL_T>...>
+{
+};
+
 #endif   // PUGS_TRAITS_HPP
diff --git a/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp b/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp
index b9f7a9af1170c146df66456a794c7c3ace6a3eee..668a77696363a23b01c01663cf9229fa3281fd45 100644
--- a/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp
+++ b/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp
@@ -27,31 +27,27 @@ class BuiltinFunctionRegister
   void
   _populateNameBuiltinFunctionMap()
   {
-    m_name_builtin_function_map.insert(
-      std::make_pair("RtoR", std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-                               std::function<double(double)>{[](double x) -> double { return x + 1; }})));
+    m_name_builtin_function_map.insert(std::make_pair("RtoR", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
+                                                                [](double x) -> double { return x + 1; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("ZtoR", std::make_shared<BuiltinFunctionEmbedder<double, int64_t>>(
-                               std::function<double(int64_t)>{[](int64_t z) -> double { return 0.5 * z; }})));
+      std::make_pair("ZtoR", std::make_shared<BuiltinFunctionEmbedder<double(int64_t)>>(
+                               [](int64_t z) -> double { return 0.5 * z; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("NtoR", std::make_shared<BuiltinFunctionEmbedder<double, uint64_t>>(
-                               std::function<double(uint64_t)>{[](uint64_t n) -> double { return 0.5 * n; }})));
+      std::make_pair("NtoR", std::make_shared<BuiltinFunctionEmbedder<double(uint64_t)>>(
+                               [](uint64_t n) -> double { return 0.5 * n; })));
 
-    m_name_builtin_function_map.insert(
-      std::make_pair("BtoR", std::make_shared<BuiltinFunctionEmbedder<double, bool>>(
-                               std::function<double(bool)>{[](bool b) -> double { return b; }})));
+    m_name_builtin_function_map.insert(std::make_pair("BtoR", std::make_shared<BuiltinFunctionEmbedder<double(bool)>>(
+                                                                [](bool b) -> double { return b; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("R2toB",
-                     std::make_shared<BuiltinFunctionEmbedder<bool, double, double>>(
-                       std::function<bool(double, double)>{[](double x, double y) -> bool { return x > y; }})));
+      std::make_pair("R2toB", std::make_shared<BuiltinFunctionEmbedder<bool(double, double)>>(
+                                [](double x, double y) -> bool { return x > y; })));
 
     m_name_builtin_function_map.insert(
-      std::make_pair("StoB",
-                     std::make_shared<BuiltinFunctionEmbedder<bool, std::string>>(
-                       std::function<bool(std::string)>{[](const std::string& s) -> bool { return s.size() > 0; }})));
+      std::make_pair("StoB", std::make_shared<BuiltinFunctionEmbedder<bool(std::string)>>(
+                               [](const std::string& s) -> bool { return s.size() > 0; })));
   }
 
  public:
diff --git a/tests/test_BuiltinFunctionEmbedder.cpp b/tests/test_BuiltinFunctionEmbedder.cpp
index f5172381c23409e416df26221f969f23bb40d2e5..052ac6fe06b8ea4c117fcdd747678c386c56cf9f 100644
--- a/tests/test_BuiltinFunctionEmbedder.cpp
+++ b/tests/test_BuiltinFunctionEmbedder.cpp
@@ -10,8 +10,7 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]")
 
   SECTION("math")
   {
-    BuiltinFunctionEmbedder<double, double> embedded_sin{
-      std::function<double(double)>{[](double x) -> double { return std::sin(x); }}};
+    BuiltinFunctionEmbedder<double(double)> embedded_sin{[](double x) -> double { return std::sin(x); }};
 
     double arg              = 2;
     DataVariant arg_variant = arg;
@@ -27,9 +26,9 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]")
 
   SECTION("multiple variant args")
   {
-    std::function<bool(double, uint64_t)> c = [](double x, uint64_t i) -> bool { return x > i; };
+    std::function c = [](double x, uint64_t i) -> bool { return x > i; };
 
-    BuiltinFunctionEmbedder<bool, double, uint64_t> embedded_c{c};
+    BuiltinFunctionEmbedder<bool(double, uint64_t)> embedded_c{c};
 
     double d_arg   = 2.3;
     uint64_t i_arg = 3;
@@ -48,12 +47,12 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]")
     REQUIRE(embedded_c.getParameterDataTypes()[1] == ASTNodeDataType::unsigned_int_t);
   }
 
-  SECTION("IBuiltinFunctionEmbedder")
+  SECTION("POD BuiltinFunctionEmbedder")
   {
-    std::function<bool(double, uint64_t)> c = [](double x, uint64_t i) -> bool { return x > i; };
+    std::function c = [](double x, uint64_t i) -> bool { return x > i; };
 
     std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
-      std::make_unique<BuiltinFunctionEmbedder<bool, double, uint64_t>>(c);
+      std::make_unique<BuiltinFunctionEmbedder<bool(double, uint64_t)>>(c);
 
     double d_arg   = 2.3;
     uint64_t i_arg = 3;
@@ -72,11 +71,196 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]")
     REQUIRE(i_embedded_c->getParameterDataTypes()[1] == ASTNodeDataType::unsigned_int_t);
   }
 
+  SECTION("void(double) BuiltinFunctionEmbedder")
+  {
+    double y = 1;
+
+    std::function add_to_y = [&](double x) -> void { y += x; };
+
+    std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
+      std::make_unique<BuiltinFunctionEmbedder<void(double)>>(add_to_y);
+
+    double x = 0.5;
+    i_embedded_c->apply(std::vector<DataVariant>{x});
+    REQUIRE(y == 1.5);
+    REQUIRE(i_embedded_c->numberOfParameters() == 1);
+    REQUIRE(i_embedded_c->getParameterDataTypes().size() == 1);
+
+    REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::void_t);
+
+    REQUIRE_THROWS_WITH(i_embedded_c->apply({std::vector<EmbeddedData>{}}),
+                        "unexpected error: unexpected argument types while casting \"" +
+                          demangle<std::vector<EmbeddedData>>() + "\" to \"" + demangle<double>() + '"');
+  }
+
+  SECTION("EmbeddedData(double, double) BuiltinFunctionEmbedder")
+  {
+    std::function sum = [&](double x, double y) -> std::shared_ptr<double> { return std::make_shared<double>(x + y); };
+
+    std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
+      std::make_unique<BuiltinFunctionEmbedder<std::shared_ptr<double>(double, double)>>(sum);
+
+    // using 4ul enforces cast test
+    REQUIRE(i_embedded_c->numberOfParameters() == 2);
+    REQUIRE(i_embedded_c->getParameterDataTypes().size() == 2);
+    REQUIRE(i_embedded_c->getParameterDataTypes()[0] == ASTNodeDataType::double_t);
+    REQUIRE(i_embedded_c->getParameterDataTypes()[1] == ASTNodeDataType::double_t);
+
+    REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::type_id_t);
+
+    DataVariant result         = i_embedded_c->apply(std::vector<DataVariant>{2.3, 4ul});
+    EmbeddedData embedded_data = std::get<EmbeddedData>(result);
+
+    const IDataHandler& handled_data = embedded_data.get();
+    const DataHandler<double>& data  = dynamic_cast<const DataHandler<double>&>(handled_data);
+    REQUIRE(*data.data_ptr() == (2.3 + 4ul));
+  }
+
+  SECTION("double(std::shared_ptr<double>) BuiltinFunctionEmbedder")
+  {
+    std::function abs = [&](std::shared_ptr<const double> x) -> double { return std::abs(*x); };
+
+    std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
+      std::make_unique<BuiltinFunctionEmbedder<double(std::shared_ptr<const double>)>>(abs);
+
+    REQUIRE(i_embedded_c->numberOfParameters() == 1);
+    REQUIRE(i_embedded_c->getParameterDataTypes().size() == 1);
+    REQUIRE(i_embedded_c->getParameterDataTypes()[0] == ASTNodeDataType::type_id_t);
+    REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::double_t);
+
+    EmbeddedData data(std::make_shared<DataHandler<const double>>(std::make_shared<const double>(-2.3)));
+    DataVariant result = i_embedded_c->apply({data});
+
+    REQUIRE(std::get<double>(result) == 2.3);
+
+    REQUIRE_THROWS_WITH(i_embedded_c->apply({2.3}),
+                        "unexpected error: unexpected argument types while casting: expecting EmbeddedData");
+
+    EmbeddedData wrong_embedded_data_type(
+      std::make_shared<DataHandler<const TinyVector<2>>>(std::make_shared<const TinyVector<2>>(-2, -2)));
+    REQUIRE_THROWS_WITH(i_embedded_c->apply({wrong_embedded_data_type}),
+                        "unexpected error: unexpected argument types while casting: "
+                        "invalid EmbeddedData type, expecting " +
+                          demangle<DataHandler<const double>>());
+  }
+
+  SECTION("uint64_t(std::vector<uint64_t>) BuiltinFunctionEmbedder")
+  {
+    std::function sum = [&](const std::vector<uint64_t>& x) -> uint64_t {
+      uint64_t sum = 0;
+      for (size_t i = 0; i < x.size(); ++i) {
+        sum += x[i];
+      }
+      return sum;
+    };
+
+    std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
+      std::make_unique<BuiltinFunctionEmbedder<uint64_t(const std::vector<uint64_t>&)>>(sum);
+
+    REQUIRE(i_embedded_c->numberOfParameters() == 1);
+    REQUIRE(i_embedded_c->getParameterDataTypes().size() == 1);
+    REQUIRE(i_embedded_c->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t);
+    REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::unsigned_int_t);
+
+    REQUIRE(std::get<uint64_t>(i_embedded_c->apply({std::vector{1ul, 2ul, 3ul}})) == 6);
+    REQUIRE(std::get<uint64_t>(i_embedded_c->apply({std::vector{1ul, 2ul, 3ul, 4ul}})) == 10);
+
+    REQUIRE_THROWS_WITH(i_embedded_c->apply({std::vector{1.2, 2.3, 3.1, 4.4}}),
+                        "unexpected error: unexpected argument types while casting \"" +
+                          demangle<std::vector<double>>() + "\" to \"" + demangle<std::vector<uint64_t>>() + '"');
+
+    REQUIRE_THROWS_WITH(i_embedded_c->apply({std::vector<EmbeddedData>{}}),
+                        "unexpected error: unexpected argument types while casting \"" +
+                          demangle<std::vector<EmbeddedData>>() + "\" to \"" + demangle<std::vector<uint64_t>>() + '"');
+  }
+
+  SECTION("uint64_t(std::vector<EmbeddedData>) BuiltinFunctionEmbedder")
+  {
+    std::function sum = [&](const std::vector<std::shared_ptr<uint64_t>>& x) -> uint64_t {
+      uint64_t sum = 0;
+      for (size_t i = 0; i < x.size(); ++i) {
+        sum += *x[i];
+      }
+      return sum;
+    };
+
+    std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
+      std::make_unique<BuiltinFunctionEmbedder<uint64_t(const std::vector<std::shared_ptr<uint64_t>>&)>>(sum);
+
+    REQUIRE(i_embedded_c->numberOfParameters() == 1);
+    REQUIRE(i_embedded_c->getParameterDataTypes().size() == 1);
+    REQUIRE(i_embedded_c->getParameterDataTypes()[0] == ASTNodeDataType::type_id_t);
+    REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::unsigned_int_t);
+
+    std::vector<EmbeddedData> embedded_data;
+    REQUIRE(std::get<uint64_t>(i_embedded_c->apply({embedded_data})) == 0);
+    embedded_data.emplace_back(std::make_shared<DataHandler<uint64_t>>(std::make_shared<uint64_t>(1)));
+    embedded_data.emplace_back(std::make_shared<DataHandler<uint64_t>>(std::make_shared<uint64_t>(2)));
+    embedded_data.emplace_back(std::make_shared<DataHandler<uint64_t>>(std::make_shared<uint64_t>(3)));
+
+    REQUIRE(std::get<uint64_t>(i_embedded_c->apply({embedded_data})) == 6);
+
+    embedded_data.emplace_back(std::make_shared<DataHandler<double>>(std::make_shared<double>(4)));
+    REQUIRE_THROWS_WITH(i_embedded_c->apply({embedded_data}),
+                        "unexpected error: unexpected argument types while casting: invalid"
+                        " EmbeddedData type, expecting " +
+                          demangle<DataHandler<uint64_t>>());
+
+    REQUIRE_THROWS_WITH(i_embedded_c->apply({TinyVector<1>{13}}),
+                        "unexpected error: unexpected argument types while casting \"" + demangle<TinyVector<1>>() +
+                          "\" to \"" + demangle<std::vector<std::shared_ptr<uint64_t>>>() + '"');
+  }
+
+  SECTION("double(void) BuiltinFunctionEmbedder")
+  {
+    std::function c = [](void) -> double { return 1.5; };
+
+    std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = std::make_unique<BuiltinFunctionEmbedder<double(void)>>(c);
+
+    REQUIRE(1.5 == c());
+    REQUIRE(std::get<double>(i_embedded_c->apply(std::vector<DataVariant>{})) == c());
+    REQUIRE(i_embedded_c->numberOfParameters() == 0);
+    REQUIRE(i_embedded_c->getParameterDataTypes().size() == 0);
+
+    REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::double_t);
+  }
+
+  SECTION("void(void) BuiltinFunctionEmbedder")
+  {
+    std::function c = [](void) -> void {};
+
+    std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = std::make_unique<BuiltinFunctionEmbedder<void(void)>>(c);
+
+    REQUIRE_NOTHROW(std::get<std::monostate>(i_embedded_c->apply(std::vector<DataVariant>{})));
+    REQUIRE(i_embedded_c->numberOfParameters() == 0);
+    REQUIRE(i_embedded_c->getParameterDataTypes().size() == 0);
+
+    REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::void_t);
+  }
+
+  SECTION("EmbeddedData(void) BuiltinFunctionEmbedder")
+  {
+    std::function c = [](void) -> std::shared_ptr<double> { return std::make_shared<double>(1.5); };
+
+    std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
+      std::make_unique<BuiltinFunctionEmbedder<std::shared_ptr<double>(void)>>(c);
+
+    REQUIRE(i_embedded_c->numberOfParameters() == 0);
+    REQUIRE(i_embedded_c->getParameterDataTypes().size() == 0);
+
+    REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::type_id_t);
+
+    const auto embedded_data         = std::get<EmbeddedData>(i_embedded_c->apply(std::vector<DataVariant>{}));
+    const IDataHandler& handled_data = embedded_data.get();
+    const DataHandler<double>& data  = dynamic_cast<const DataHandler<double>&>(handled_data);
+    REQUIRE(*data.data_ptr() == 1.5);
+  }
+
   SECTION("error")
   {
-    std::function<bool(double)> positive = [](double x) -> bool { return x >= 0; };
+    std::function positive = [](double x) -> bool { return x >= 0; };
 
-    BuiltinFunctionEmbedder<bool, double> embedded_positive{positive};
+    BuiltinFunctionEmbedder<bool(double)> embedded_positive{positive};
 
     std::string arg = std::string{"2.3"};
 
diff --git a/tests/test_BuiltinFunctionEmbedderTable.cpp b/tests/test_BuiltinFunctionEmbedderTable.cpp
index 09b9d7c1f7beafa7ef26cfd288f4a8746b530e0c..5cc254f190a07c6162053ea522627ac0eeb49586 100644
--- a/tests/test_BuiltinFunctionEmbedderTable.cpp
+++ b/tests/test_BuiltinFunctionEmbedderTable.cpp
@@ -13,15 +13,14 @@ TEST_CASE("BuiltinFunctionEmbedderTable", "[language]")
 
   REQUIRE(table.size() == 0);
 
-  std::shared_ptr<IBuiltinFunctionEmbedder> embedded_sin = std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-    std::function<double(double)>{[](double x) -> double { return std::sin(x); }});
+  std::shared_ptr<IBuiltinFunctionEmbedder> embedded_sin =
+    std::make_shared<BuiltinFunctionEmbedder<double(double)>>([](double x) -> double { return std::sin(x); });
   table.add(embedded_sin);
 
   REQUIRE(table.size() == 1);
 
   std::shared_ptr<IBuiltinFunctionEmbedder> embedded_greater =
-    std::make_shared<BuiltinFunctionEmbedder<bool, int, int>>(
-      std::function<bool(int, int)>{[](int i, int j) -> bool { return i > j; }});
+    std::make_shared<BuiltinFunctionEmbedder<bool(int, int)>>([](int i, int j) -> bool { return i > j; });
   table.add(embedded_greater);
 
   REQUIRE(table.size() == 2);
diff --git a/tests/test_SymbolTable.cpp b/tests/test_SymbolTable.cpp
index 7eadfc31426ac7cc7154a60d1d0d4c6a4e8649c5..bb80c4999781e59f3585f1ff64eba3ac3b71bcac 100644
--- a/tests/test_SymbolTable.cpp
+++ b/tests/test_SymbolTable.cpp
@@ -213,8 +213,8 @@ TEST_CASE("SymbolTable", "[language]")
     const auto& const_builtin_function_table = static_cast<const SymbolTable&>(*root_st).builtinFunctionEmbedderTable();
     REQUIRE(const_builtin_function_table.size() == 0);
 
-    builtin_function_table.add(std::make_shared<BuiltinFunctionEmbedder<double, double>>(
-      std::function<double(double)>{[](double) -> double { return 0; }}));
+    builtin_function_table.add(
+      std::make_shared<BuiltinFunctionEmbedder<double(double)>>([](double) -> double { return 0; }));
 
     REQUIRE(builtin_function_table.size() == 1);
     REQUIRE(const_builtin_function_table.size() == 1);