uCalc API Version: 2.1.3-preview.2 Released: 6/16/2026

Warning

uCalc API Preview Release Notice:The documentation describes the intended behavior of the API. The current preview build contains incomplete features, unoptimized performance, and is subject to breaking changes.

DefineFunction

Method

Product: 

Fast Math Parser

Class: 

uCalcBase

Registers a user-defined function for use in expressions, supporting inline definitions, external callbacks, and advanced features like overloading and recursion.

Syntax

DefineFunction(string, OpCallback, DataType, bool, bool)

Parameters

definition
string
The function signature and body, e.g., "MyFunc(x, y) = x + y".
functionAddr
OpCallback
(Default = 0)
The address of a native callback function that implements the function's logic. If provided, the expression body in the definition string is ignored.
returnType
DataType
(Default = Empty)
The return [DataType] of the function. If omitted, the type is often inferred from the expression body.
bootstrap
bool
(Default = false)
If true, allows the new function definition to call a pre-existing function of the same name, preventing recursion. Useful for wrapping or extending existing functions.
overwrite
bool
(Default = false)
If true, this definition replaces any existing function with the same signature, and automatically updates all previously parsed expressions that use it. Essential for reactive, spreadsheet-like behavior.

Return

Item

An [Item] object representing the newly defined function, which can be used for later modification or release.

Remarks

The DefineFunction method is a cornerstone of uCalc, allowing you to create custom functions for use in expressions. You can define functions in two primary ways:

  1. Inline Definition: Provide the entire function signature and logic as a single string.
  2. Callback Binding: Provide a function signature and link it to a native C#, C++, or VB function in your host application.

This flexibility makes it ideal for everything from simple user-defined helpers to complex integrations with existing code.

📖 Function Syntax

A function definition string follows this pattern:

FunctionName(param1, param2, ...) As ReturnType = expression

  • Parameters: A comma-separated list of parameter names. You can optionally assign a data type to a parameter by following it with As [typename]. Parentheses () are required even for functions with no parameters.
  • Return Type: Optional. If omitted, uCalc attempts to infer it. If it can't, it uses the instance's DefaultDataType.
  • Expression: The logic to be executed when the function is called.

⚙️ Core Features

FeatureDescription
OverloadingDefine multiple functions with the same name but different parameter types or counts. uCalc selects the correct one at runtime based on the arguments provided.
Optional ParametersSpecify default values for parameters, e.g., MyFunc(x, y = 5).
Variadic FunctionsCreate functions that accept a variable number of arguments using the ... syntax, e.g., Average(x ...)
RecursionFunctions can call themselves, enabling classic recursive algorithms like factorial or Fibonacci.
Shadowing vs. OverwritingBy default, a new definition shadows an old one; existing expressions still use the old version. Setting overwrite: true replaces the old definition everywhere, enabling powerful spreadsheet-like reactive updates.
BootstrappingSetting bootstrap: true lets you redefine a function by calling the original version within its new definition, which is perfect for extending or wrapping built-in functions without causing a recursive loop.

🔗 Argument Passing Modifiers

uCalc extends standard argument passing with powerful custom modifiers that provide deep introspection and control.

ModifierDescription
ByVal(Default) Passes the evaluated result of the argument.
ByRefPasses a reference to a variable, allowing the function to modify its value.
ByHandlePasses the argument's underlying Item object. This allows the callback to inspect metadata like the argument's name, data type, or original expression text.
ByExprPasses the argument as an unevaluated Expression object. This enables powerful lazy-evaluation and short-circuiting logic, as seen in the built-in IIf function.

💡 Comparative Analysis

  • vs. Compiled Languages (C#/C++): The primary advantage is dynamism. Functions can be defined at runtime from user input, configuration files, or database entries without requiring recompilation. This is fundamental for applications like report generators, scripting environments, and scientific modelers.

  • vs. Other Scripting Engines (Lua, Python): While full scripting engines are more powerful, they are also much heavier. uCalc is a lightweight, specialized component. Its key differentiators are:

    • ByExpr and ByHandle: These provide metaprogramming capabilities that are often complex or impossible to achieve in other embedded script engines.
    • Overwrite Flag: This built-in feature for creating reactive dependencies is a unique and powerful concept that simplifies building spreadsheet-like applications, a task that would require significant manual dependency tracking in other systems.

📋 Retrieving Defined Functions

You can get a list of all currently defined functions using uc.ListOfItems(ItemIs.Function).

Examples

A minimal example defining a function inline to calculate the area of a rectangle.
				
					using uCalcSoftware;

var uc = new uCalc();
uc.DefineFunction("Area(length, width) = length * width");
Console.WriteLine(uc.Eval("Area(4, 5)"));
				
			
20
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   uc.DefineFunction("Area(length, width) = length * width");
   cout << uc.Eval("Area(4, 5)") << endl;
}
				
			
20
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      uc.DefineFunction("Area(length, width) = length * width")
      Console.WriteLine(uc.Eval("Area(4, 5)"))
   End Sub
End Module
				
			
20
Demonstrates defining a function that is implemented by a native callback in the host application.
				
					using uCalcSoftware;

var uc = new uCalc();

static void MyAreaCallback(uCalc.Callback cb) {
   var length = cb.Arg(1);
   var width = cb.Arg(2);
   cb.Return(length * width);
}


// The signature is defined, but the logic is provided by 'MyAreaCallback'.
uc.DefineFunction("Area(x, y)", MyAreaCallback);
Console.WriteLine(uc.Eval("Area(3, 4)"));
				
			
12
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

void ucalc_call MyAreaCallback(uCalcBase::Callback cb) {
   auto length = cb.Arg(1);
   auto width = cb.Arg(2);
   cb.Return(length * width);
}

int main() {
   uCalc uc;
   // The signature is defined, but the logic is provided by 'MyAreaCallback'.
   uc.DefineFunction("Area(x, y)", MyAreaCallback);
   cout << uc.Eval("Area(3, 4)") << endl;
}
				
			
12
				
					Imports System
Imports uCalcSoftware
Public Module Program
   
   Public Sub MyAreaCallback(ByVal cb As uCalc.Callback)
      Dim length = cb.Arg(1)
      Dim width = cb.Arg(2)
      cb.Return(length * width)
   End Sub
   
   Public Sub Main()
      Dim uc As New uCalc()
      '// The signature is defined, but the logic is provided by 'MyAreaCallback'.
      uc.DefineFunction("Area(x, y)", AddressOf MyAreaCallback)
      Console.WriteLine(uc.Eval("Area(3, 4)"))
   End Sub
End Module
				
			
12
Shows how to create overloaded functions that uCalc distinguishes based on parameter count and type.
				
					using uCalcSoftware;

var uc = new uCalc();
// Overload for two numbers
uc.DefineFunction("Combine(x, y) = x + y");

// Overload for two strings
uc.DefineFunction("Combine(x As String, y As String) As String = x + y");

// Overload for three numbers
uc.DefineFunction("Combine(x, y, z) = x + y + z");

Console.WriteLine($"Two numbers: {uc.EvalStr("Combine(5, 10)")}");
Console.WriteLine($"Two strings: {uc.EvalStr("Combine('Hello, ', 'World!')")}");
Console.WriteLine($"Three numbers: {uc.EvalStr("Combine(5, 10, 20)")}");
				
			
Two numbers: 15
Two strings: Hello, World!
Three numbers: 35
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   // Overload for two numbers
   uc.DefineFunction("Combine(x, y) = x + y");

   // Overload for two strings
   uc.DefineFunction("Combine(x As String, y As String) As String = x + y");

   // Overload for three numbers
   uc.DefineFunction("Combine(x, y, z) = x + y + z");

   cout << "Two numbers: " << uc.EvalStr("Combine(5, 10)") << endl;
   cout << "Two strings: " << uc.EvalStr("Combine('Hello, ', 'World!')") << endl;
   cout << "Three numbers: " << uc.EvalStr("Combine(5, 10, 20)") << endl;
}
				
			
Two numbers: 15
Two strings: Hello, World!
Three numbers: 35
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      '// Overload for two numbers
      uc.DefineFunction("Combine(x, y) = x + y")
      
      '// Overload for two strings
      uc.DefineFunction("Combine(x As String, y As String) As String = x + y")
      
      '// Overload for three numbers
      uc.DefineFunction("Combine(x, y, z) = x + y + z")
      
      Console.WriteLine($"Two numbers: {uc.EvalStr("Combine(5, 10)")}")
      Console.WriteLine($"Two strings: {uc.EvalStr("Combine('Hello, ', 'World!')")}")
      Console.WriteLine($"Three numbers: {uc.EvalStr("Combine(5, 10, 20)")}")
   End Sub
End Module
				
			
Two numbers: 15
Two strings: Hello, World!
Three numbers: 35
Defines a recursive Factorial function using the IIf function for conditional logic.
				
					using uCalcSoftware;

var uc = new uCalc();
uc.DefineFunction("Factorial(n) = IIf(n > 1, n * Factorial(n - 1), 1)");
Console.WriteLine(uc.Eval("Factorial(5)"));
				
			
120
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   uc.DefineFunction("Factorial(n) = IIf(n > 1, n * Factorial(n - 1), 1)");
   cout << uc.Eval("Factorial(5)") << endl;
}
				
			
120
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      uc.DefineFunction("Factorial(n) = IIf(n > 1, n * Factorial(n - 1), 1)")
      Console.WriteLine(uc.Eval("Factorial(5)"))
   End Sub
End Module
				
			
120
Miscellaneous end-user functions defined with DefineFunction()
				
					using uCalcSoftware;

var uc = new uCalc();
Console.WriteLine("---- Simple function def ----");
uc.DefineFunction("f(x) = x ^ 2 + 5");
Console.WriteLine(uc.Eval("f(10)"));

Console.WriteLine("---- Function overloading ----");
// Overloading based on parameter type or number of parameters
uc.DefineFunction("MyOverload(x As Double) = x + x");
uc.DefineFunction("MyOverload(x As String) As String = x + x");
uc.DefineFunction("MyOverload(x As String, y As String) As String = x + y");
uc.DefineFunction("MyOverload(x, y) = x + y");
Console.WriteLine(uc.EvalStr("MyOverload(5)"));
Console.WriteLine(uc.EvalStr("MyOverload('Ha')"));
Console.WriteLine(uc.EvalStr("MyOverload('Hello ', 'world!')"));
Console.WriteLine(uc.EvalStr("MyOverload(5, 10)"));

Console.WriteLine("---- Definition hiding/un-hiding ----");
// Shadowing (hiding) definitions
uc.DefineFunction("h(x) = x * 10");
Console.WriteLine(uc.Eval("h(3)"));
var hFunc = uc.DefineFunction("h(x) = x * 100"); // hides previous def
Console.WriteLine(uc.Eval("h(3)"));
hFunc.Release(); // Releasing this restores previous def
Console.WriteLine(uc.Eval("h(3)"));

Console.WriteLine("---- Optional parameters ----");
uc.DefineFunction("Opt(x, y = 5, z As String = 'Hello') = x + y + Length(z)");
Console.WriteLine(uc.Eval("Opt(10)"));
Console.WriteLine(uc.Eval("Opt(10, 20)"));
Console.WriteLine(uc.Eval("Opt(10, 20, 'Just a test 123')"));

Console.WriteLine("---- Recursion ----");
uc.DefineFunction("Factorial(x) = iif(x > 1, x * Factorial(x - 1), 1)");
uc.DefineFunction("Fib(n) = IIf(n < 2, n, Fib(n - 1) + Fib(n - 2))");
Console.WriteLine(uc.Eval("Factorial(5)"));
Console.WriteLine(uc.Eval("Fib(10)"));

// Bootstrap - builds new def on top of existing one
Console.WriteLine("------ Bootstrapping -------");
Console.WriteLine(uc.EvalStr("Hex(123)")); // uses "built-in" version of Hex()

var MyHex = uc.DefineFunction("Hex(number As Int) As String = '0x' + UCase(Hex(number))", bootstrap: true);

Console.WriteLine(uc.EvalStr("Hex(123)"));
MyHex.Release();
Console.WriteLine(uc.EvalStr("Hex(123)"));

// Overwrite - useful for spreadsheet-like functionality
Console.WriteLine("------ Overwrite -------");

uc.DefineFunction("SpreadsheetCell_A1() = 5", overwrite: true);
uc.DefineFunction("SpreadsheetCell_B2() = SpreadsheetCell_A1() * 10", overwrite: true);
uc.DefineFunction("SpreadsheetCell_C3() = SpreadsheetCell_A1() + SpreadsheetCell_B2()", overwrite: true);

Console.WriteLine(uc.Eval("SpreadsheetCell_A1()"));
Console.WriteLine(uc.Eval("SpreadsheetCell_B2()"));
Console.WriteLine(uc.Eval("SpreadsheetCell_C3()"));
// SpreadsheetCell_C3() will be affected by the definition changes of SpreadsheetCell_A1() and  SpreadsheetCell_B3()

uc.DefineFunction("SpreadsheetCell_B2() = SpreadsheetCell_A1() * 100", overwrite: true);
uc.DefineFunction("SpreadsheetCell_A1() = 25", overwrite: true);

Console.WriteLine("-------");
// Note: Empty parenthesis are optional for functions with no parameters
Console.WriteLine(uc.Eval("SpreadsheetCell_A1"));
Console.WriteLine(uc.Eval("SpreadsheetCell_B2"));
Console.WriteLine(uc.Eval("SpreadsheetCell_C3"));

// See Define() topic for more





				
			
---- Simple function def ----
105
---- Function overloading ----
10
HaHa
Hello world!
15
---- Definition hiding/un-hiding ----
30
300
30
---- Optional parameters ----
20
35
45
---- Recursion ----
120
55
------ Bootstrapping -------
7b
0x7B
7b
------ Overwrite -------
5
50
55
-------
25
2500
2525
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   cout << "---- Simple function def ----" << endl;
   uc.DefineFunction("f(x) = x ^ 2 + 5");
   cout << uc.Eval("f(10)") << endl;

   cout << "---- Function overloading ----" << endl;
   // Overloading based on parameter type or number of parameters
   uc.DefineFunction("MyOverload(x As Double) = x + x");
   uc.DefineFunction("MyOverload(x As String) As String = x + x");
   uc.DefineFunction("MyOverload(x As String, y As String) As String = x + y");
   uc.DefineFunction("MyOverload(x, y) = x + y");
   cout << uc.EvalStr("MyOverload(5)") << endl;
   cout << uc.EvalStr("MyOverload('Ha')") << endl;
   cout << uc.EvalStr("MyOverload('Hello ', 'world!')") << endl;
   cout << uc.EvalStr("MyOverload(5, 10)") << endl;

   cout << "---- Definition hiding/un-hiding ----" << endl;
   // Shadowing (hiding) definitions
   uc.DefineFunction("h(x) = x * 10");
   cout << uc.Eval("h(3)") << endl;
   auto hFunc = uc.DefineFunction("h(x) = x * 100"); // hides previous def
   cout << uc.Eval("h(3)") << endl;
   hFunc.Release(); // Releasing this restores previous def
   cout << uc.Eval("h(3)") << endl;

   cout << "---- Optional parameters ----" << endl;
   uc.DefineFunction("Opt(x, y = 5, z As String = 'Hello') = x + y + Length(z)");
   cout << uc.Eval("Opt(10)") << endl;
   cout << uc.Eval("Opt(10, 20)") << endl;
   cout << uc.Eval("Opt(10, 20, 'Just a test 123')") << endl;

   cout << "---- Recursion ----" << endl;
   uc.DefineFunction("Factorial(x) = iif(x > 1, x * Factorial(x - 1), 1)");
   uc.DefineFunction("Fib(n) = IIf(n < 2, n, Fib(n - 1) + Fib(n - 2))");
   cout << uc.Eval("Factorial(5)") << endl;
   cout << uc.Eval("Fib(10)") << endl;

   // Bootstrap - builds new def on top of existing one
   cout << "------ Bootstrapping -------" << endl;
   cout << uc.EvalStr("Hex(123)") << endl; // uses "built-in" version of Hex()
   auto MyHex = uc.DefineFunction("Hex(number As Int) As String = '0x' + UCase(Hex(number))", 0, uCalc::DataType::Empty, true);


   cout << uc.EvalStr("Hex(123)") << endl;
   MyHex.Release();
   cout << uc.EvalStr("Hex(123)") << endl;

   // Overwrite - useful for spreadsheet-like functionality
   cout << "------ Overwrite -------" << endl;
   uc.DefineFunction("SpreadsheetCell_A1() = 5", 0, uCalc::DataType::Empty, false, true);
   uc.DefineFunction("SpreadsheetCell_B2() = SpreadsheetCell_A1() * 10", 0, uCalc::DataType::Empty, false, true);
   uc.DefineFunction("SpreadsheetCell_C3() = SpreadsheetCell_A1() + SpreadsheetCell_B2()", 0, uCalc::DataType::Empty, false, true);


   cout << uc.Eval("SpreadsheetCell_A1()") << endl;
   cout << uc.Eval("SpreadsheetCell_B2()") << endl;
   cout << uc.Eval("SpreadsheetCell_C3()") << endl;
   // SpreadsheetCell_C3() will be affected by the definition changes of SpreadsheetCell_A1() and  SpreadsheetCell_B3()
   uc.DefineFunction("SpreadsheetCell_B2() = SpreadsheetCell_A1() * 100", 0, uCalc::DataType::Empty, false, true);
   uc.DefineFunction("SpreadsheetCell_A1() = 25", 0, uCalc::DataType::Empty, false, true);


   cout << "-------" << endl;
   // Note: Empty parenthesis are optional for functions with no parameters
   cout << uc.Eval("SpreadsheetCell_A1") << endl;
   cout << uc.Eval("SpreadsheetCell_B2") << endl;
   cout << uc.Eval("SpreadsheetCell_C3") << endl;

   // See Define() topic for more





}
				
			
---- Simple function def ----
105
---- Function overloading ----
10
HaHa
Hello world!
15
---- Definition hiding/un-hiding ----
30
300
30
---- Optional parameters ----
20
35
45
---- Recursion ----
120
55
------ Bootstrapping -------
7b
0x7B
7b
------ Overwrite -------
5
50
55
-------
25
2500
2525
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Console.WriteLine("---- Simple function def ----")
      uc.DefineFunction("f(x) = x ^ 2 + 5")
      Console.WriteLine(uc.Eval("f(10)"))
      
      Console.WriteLine("---- Function overloading ----")
      '// Overloading based on parameter type or number of parameters
      uc.DefineFunction("MyOverload(x As Double) = x + x")
      uc.DefineFunction("MyOverload(x As String) As String = x + x")
      uc.DefineFunction("MyOverload(x As String, y As String) As String = x + y")
      uc.DefineFunction("MyOverload(x, y) = x + y")
      Console.WriteLine(uc.EvalStr("MyOverload(5)"))
      Console.WriteLine(uc.EvalStr("MyOverload('Ha')"))
      Console.WriteLine(uc.EvalStr("MyOverload('Hello ', 'world!')"))
      Console.WriteLine(uc.EvalStr("MyOverload(5, 10)"))
      
      Console.WriteLine("---- Definition hiding/un-hiding ----")
      '// Shadowing (hiding) definitions
      uc.DefineFunction("h(x) = x * 10")
      Console.WriteLine(uc.Eval("h(3)"))
      Dim hFunc = uc.DefineFunction("h(x) = x * 100") '// hides previous def
      Console.WriteLine(uc.Eval("h(3)"))
      hFunc.Release() '// Releasing this restores previous def
      Console.WriteLine(uc.Eval("h(3)"))
      
      Console.WriteLine("---- Optional parameters ----")
      uc.DefineFunction("Opt(x, y = 5, z As String = 'Hello') = x + y + Length(z)")
      Console.WriteLine(uc.Eval("Opt(10)"))
      Console.WriteLine(uc.Eval("Opt(10, 20)"))
      Console.WriteLine(uc.Eval("Opt(10, 20, 'Just a test 123')"))
      
      Console.WriteLine("---- Recursion ----")
      uc.DefineFunction("Factorial(x) = iif(x > 1, x * Factorial(x - 1), 1)")
      uc.DefineFunction("Fib(n) = IIf(n < 2, n, Fib(n - 1) + Fib(n - 2))")
      Console.WriteLine(uc.Eval("Factorial(5)"))
      Console.WriteLine(uc.Eval("Fib(10)"))
      
      '// Bootstrap - builds new def on top of existing one
      Console.WriteLine("------ Bootstrapping -------")
      Console.WriteLine(uc.EvalStr("Hex(123)")) '// uses "built-in" version of Hex()
      
      
      Dim MyHex = uc.DefineFunction("Hex(number As Int) As String = '0x' + UCase(Hex(number))", bootstrap:=True)
      Console.WriteLine(uc.EvalStr("Hex(123)"))
      MyHex.Release()
      Console.WriteLine(uc.EvalStr("Hex(123)"))
      
      '// Overwrite - useful for spreadsheet-like functionality
      Console.WriteLine("------ Overwrite -------")
      
      
      uc.DefineFunction("SpreadsheetCell_A1() = 5", overwrite:=true)
      uc.DefineFunction("SpreadsheetCell_B2() = SpreadsheetCell_A1() * 10", Overwrite:=true)
      uc.DefineFunction("SpreadsheetCell_C3() = SpreadsheetCell_A1() + SpreadsheetCell_B2()", overwrite:=true)
      Console.WriteLine(uc.Eval("SpreadsheetCell_A1()"))
      Console.WriteLine(uc.Eval("SpreadsheetCell_B2()"))
      Console.WriteLine(uc.Eval("SpreadsheetCell_C3()"))
      '// SpreadsheetCell_C3() will be affected by the definition changes of SpreadsheetCell_A1() and  SpreadsheetCell_B3()
      
      
      uc.DefineFunction("SpreadsheetCell_B2() = SpreadsheetCell_A1() * 100", overwrite:=true)
      uc.DefineFunction("SpreadsheetCell_A1() = 25", overwrite:=true)
      Console.WriteLine("-------")
      '// Note: Empty parenthesis are optional for functions with no parameters
      Console.WriteLine(uc.Eval("SpreadsheetCell_A1"))
      Console.WriteLine(uc.Eval("SpreadsheetCell_B2"))
      Console.WriteLine(uc.Eval("SpreadsheetCell_C3"))
      
      '// See Define() topic for more
      
      
      
      
      
   End Sub
End Module
				
			
---- Simple function def ----
105
---- Function overloading ----
10
HaHa
Hello world!
15
---- Definition hiding/un-hiding ----
30
300
30
---- Optional parameters ----
20
35
45
---- Recursion ----
120
55
------ Bootstrapping -------
7b
0x7B
7b
------ Overwrite -------
5
50
55
-------
25
2500
2525
Defining a callback function with a variable number of arguments
				
					using uCalcSoftware;

var uc = new uCalc();

static void MyAverage(uCalc.Callback cb) {
   double Total = 0;
   for (int x = 1; x <= cb.ArgCount(); x++) {
      Total = Total + cb.Arg(x);
   }
   cb.Return(Total / cb.ArgCount());
}

uc.DefineFunction("Average(x ...)", MyAverage);
Console.WriteLine(uc.Eval("Average(10, 3, 7, 4)"));
				
			
6
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

void ucalc_call MyAverage(uCalcBase::Callback cb) {
   double Total = 0;
   for (int x = 1; x <= cb.ArgCount(); x++) {
      Total = Total + cb.Arg(x);
   }
   cb.Return(Total / cb.ArgCount());
}
int main() {
   uCalc uc;
   uc.DefineFunction("Average(x ...)", MyAverage);
   cout << uc.Eval("Average(10, 3, 7, 4)") << endl;
}
				
			
6
				
					Imports System
Imports uCalcSoftware
Public Module Program
   
   Public Sub MyAverage(ByVal cb As uCalc.Callback)
      Dim Total As Double = 0
      For x  As Integer = 1 To cb.ArgCount()
         Total = Total + cb.Arg(x)
      Next
      cb.Return(Total / cb.ArgCount())
   End Sub
   Public Sub Main()
      Dim uc As New uCalc()
      uc.DefineFunction("Average(x ...)", AddressOf MyAverage)
      Console.WriteLine(uc.Eval("Average(10, 3, 7, 4)"))
   End Sub
End Module
				
			
6
Passing arg ByHandle to retrieve meta data such as arg data type; and AnyType
				
					using uCalcSoftware;

var uc = new uCalc();

static void DisplayArgs(uCalc.Callback cb) {
   for (int x = 1; x <= cb.ArgCount(); x++) {
      Console.WriteLine(cb.ArgItem(x).ValueStr() + "  Type: " + cb.ArgItem(x).DataType.Name);
   }
}

uc.DefineFunction("DisplayArgs(ByHandle Arg As AnyType ...)", DisplayArgs);
uc.Eval("DisplayArgs(5, 3+2*#i, 'Hello', True, False, Int16(5+4.1))");
				
			
5  Type: double
3+2i  Type: complex
Hello  Type: string
true  Type: bool
false  Type: bool
9  Type: int16
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

void ucalc_call DisplayArgs(uCalcBase::Callback cb) {
   for (int x = 1; x <= cb.ArgCount(); x++) {
      cout << cb.ArgItem(x).ValueStr() + "  Type: " + cb.ArgItem(x).DataType().Name() << endl;
   }
}
int main() {
   uCalc uc;
   uc.DefineFunction("DisplayArgs(ByHandle Arg As AnyType ...)", DisplayArgs);
   uc.Eval("DisplayArgs(5, 3+2*#i, 'Hello', True, False, Int16(5+4.1))");
}
				
			
5  Type: double
3+2i  Type: complex
Hello  Type: string
true  Type: bool
false  Type: bool
9  Type: int16
				
					Imports System
Imports uCalcSoftware
Public Module Program
   
   Public Sub DisplayArgs(ByVal cb As uCalc.Callback)
      For x  As Integer = 1 To cb.ArgCount()
         Console.WriteLine(cb.ArgItem(x).ValueStr() + "  Type: " + cb.ArgItem(x).DataType.Name)
      Next
   End Sub
   Public Sub Main()
      Dim uc As New uCalc()
      uc.DefineFunction("DisplayArgs(ByHandle Arg As AnyType ...)", AddressOf DisplayArgs)
      uc.Eval("DisplayArgs(5, 3+2*#i, 'Hello', True, False, Int16(5+4.1))")
   End Sub
End Module
				
			
5  Type: double
3+2i  Type: complex
Hello  Type: string
true  Type: bool
false  Type: bool
9  Type: int16
Passing arg ByExpr
				
					using uCalcSoftware;

var uc = new uCalc();

static void MySum(uCalc.Callback cb) {
   var Total = 0.0;
   var Expr = cb.ArgExpr(1);
   var Start = cb.Arg(2);
   var Finish = cb.Arg(3);
   var Variable = cb.ArgItem(4);

   for (double x = Start; x <= Finish; x++) {
      Variable.Value(x);
      Total += Expr.Evaluate();
   }
   cb.Return(Total);
}

uc.DefineVariable("x");
uc.DefineFunction("Sum(ByExpr Expr, Start, Finish, ByHandle Var)", MySum);
Console.WriteLine(uc.Eval("Sum(x ^ 2, 1, 10, x)"));

				
			
385
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

void ucalc_call MySum(uCalcBase::Callback cb) {
   auto Total = 0.0;
   auto Expr = cb.ArgExpr(1);
   auto Start = cb.Arg(2);
   auto Finish = cb.Arg(3);
   auto Variable = cb.ArgItem(4);

   for (double x = Start; x <= Finish; x++) {
      Variable.Value(x);
      Total += Expr.Evaluate();
   }
   cb.Return(Total);
}
int main() {
   uCalc uc;
   uc.DefineVariable("x");
   uc.DefineFunction("Sum(ByExpr Expr, Start, Finish, ByHandle Var)", MySum);
   cout << uc.Eval("Sum(x ^ 2, 1, 10, x)") << endl;

}
				
			
385
				
					Imports System
Imports uCalcSoftware
Public Module Program
   
   Public Sub MySum(ByVal cb As uCalc.Callback)
      Dim Total = 0.0
      Dim Expr = cb.ArgExpr(1)
      Dim Start = cb.Arg(2)
      Dim Finish = cb.Arg(3)
      Dim Variable = cb.ArgItem(4)
      
      For x  As Double = Start To Finish
         Variable.Value(x)
         Total += Expr.Evaluate()
      Next
      cb.Return(Total)
   End Sub
   Public Sub Main()
      Dim uc As New uCalc()
      uc.DefineVariable("x")
      uc.DefineFunction("Sum(ByExpr Expr, Start, Finish, ByHandle Var)", AddressOf MySum)
      Console.WriteLine(uc.Eval("Sum(x ^ 2, 1, 10, x)"))
      
   End Sub
End Module
				
			
385
Returning a string (from a callback)
				
					using uCalcSoftware;

var uc = new uCalc();

static void TwiceStr(uCalc.Callback cb) {
   cb.ReturnStr(cb.ArgStr(1) + cb.ArgStr(1));
}

uc.DefineFunction("Twice(Txt As String) As String", TwiceStr);
Console.WriteLine(uc.EvalStr("Twice('Bye')"));
				
			
ByeBye
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

void ucalc_call TwiceStr(uCalcBase::Callback cb) {
   cb.ReturnStr(cb.ArgStr(1) + cb.ArgStr(1));
}
int main() {
   uCalc uc;
   uc.DefineFunction("Twice(Txt As String) As String", TwiceStr);
   cout << uc.EvalStr("Twice('Bye')") << endl;
}
				
			
ByeBye
				
					Imports System
Imports uCalcSoftware
Public Module Program
   
   Public Sub TwiceStr(ByVal cb As uCalc.Callback)
      cb.ReturnStr(cb.ArgStr(1) + cb.ArgStr(1))
   End Sub
   Public Sub Main()
      Dim uc As New uCalc()
      uc.DefineFunction("Twice(Txt As String) As String", AddressOf TwiceStr)
      Console.WriteLine(uc.EvalStr("Twice('Bye')"))
   End Sub
End Module
				
			
ByeBye
How to handle and retrieve various data types (including pointers) within a callback.
				
					using uCalcSoftware;

var uc = new uCalc();

static void MyFunction(uCalc.Callback cb) {
   var uc = cb.uCalc;
   Console.WriteLine("------ MyFunc ------");

   // Retrieve standard 32-bit and 64-bit integer arguments directly
   Console.WriteLine(cb.ArgInt32(1));
   Console.WriteLine(cb.ArgInt64(2));

   // Retrieve the value of a pointer argument by referencing its exact data type.
   Console.WriteLine(uc.ItemOf("Int8").DataType.ToString(cb.ArgAddr(3)));

   // The Item object correctly identifies the type before conversion
   Console.WriteLine(uc.ItemOf("Int").DataType.ToString(cb.ArgPtr(4)));
}

static void MyFunction2(uCalc.Callback cb) {
   var uc = cb.uCalc;
   Console.WriteLine("------ MyFunc2 ------");
   Console.WriteLine(uc.DataTypeOf(BuiltInType.Integer_8).ToString(cb.ArgPtr(1)));
}

static void MyFunction3(uCalc.Callback cb) {
   var uc = cb.uCalc;
   Console.WriteLine("------ MyFunc3 ------");
   Console.WriteLine(uc.DataTypeOf(BuiltInType.Integer_16).ToString(cb.ArgPtr(1)));
}

uc.DefineVariable("x As Int = 123"); // Int32
uc.DefineVariable("xPtr As Int Ptr = AddressOf(x)");
uc.DefineFunction("MyFunc(a As Int32, b As Int64, c As Byte, d As Int Ptr)", MyFunction);
uc.Eval("MyFunc(x*10, 1+1, 255, xPtr)");

uc.DefineVariable("x2 As Int8 = -123");
uc.DefineVariable("xPtr2 As Int8 Ptr = AddressOf(x2)");
uc.DefineFunction("MyFunc2(d As Int8 Ptr)", MyFunction2);
uc.Eval("MyFunc2(xPtr2)");

uc.DefineVariable("x3 As Int16 = 1234");
uc.DefineVariable("xPtr3 As Int16 Ptr = AddressOf(x3)");
uc.DefineFunction("MyFunc3(d As Int16 Ptr)", MyFunction3);
uc.Eval("MyFunc3(xPtr3)");
				
			
------ MyFunc ------
1230
2
-1
123
------ MyFunc2 ------
-123
------ MyFunc3 ------
1234
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

void ucalc_call MyFunction(uCalcBase::Callback cb) {
   auto uc = cb.uCalc();
   cout << "------ MyFunc ------" << endl;

   // Retrieve standard 32-bit and 64-bit integer arguments directly
   cout << cb.ArgInt32(1) << endl;
   cout << cb.ArgInt64(2) << endl;

   // Retrieve the value of a pointer argument by referencing its exact data type.
   cout << uc.ItemOf("Int8").DataType().ToString(cb.ArgAddr(3)) << endl;

   // The Item object correctly identifies the type before conversion
   cout << uc.ItemOf("Int").DataType().ToString(cb.ArgPtr(4)) << endl;
}

void ucalc_call MyFunction2(uCalcBase::Callback cb) {
   auto uc = cb.uCalc();
   cout << "------ MyFunc2 ------" << endl;
   cout << uc.DataTypeOf(BuiltInType::Integer_8).ToString(cb.ArgPtr(1)) << endl;
}

void ucalc_call MyFunction3(uCalcBase::Callback cb) {
   auto uc = cb.uCalc();
   cout << "------ MyFunc3 ------" << endl;
   cout << uc.DataTypeOf(BuiltInType::Integer_16).ToString(cb.ArgPtr(1)) << endl;
}
int main() {
   uCalc uc;
   uc.DefineVariable("x As Int = 123"); // Int32
   uc.DefineVariable("xPtr As Int Ptr = AddressOf(x)");
   uc.DefineFunction("MyFunc(a As Int32, b As Int64, c As Byte, d As Int Ptr)", MyFunction);
   uc.Eval("MyFunc(x*10, 1+1, 255, xPtr)");

   uc.DefineVariable("x2 As Int8 = -123");
   uc.DefineVariable("xPtr2 As Int8 Ptr = AddressOf(x2)");
   uc.DefineFunction("MyFunc2(d As Int8 Ptr)", MyFunction2);
   uc.Eval("MyFunc2(xPtr2)");

   uc.DefineVariable("x3 As Int16 = 1234");
   uc.DefineVariable("xPtr3 As Int16 Ptr = AddressOf(x3)");
   uc.DefineFunction("MyFunc3(d As Int16 Ptr)", MyFunction3);
   uc.Eval("MyFunc3(xPtr3)");
}
				
			
------ MyFunc ------
1230
2
-1
123
------ MyFunc2 ------
-123
------ MyFunc3 ------
1234
				
					Imports System
Imports uCalcSoftware
Public Module Program
   
   Public Sub MyFunction(ByVal cb As uCalc.Callback)
      Dim uc = cb.uCalc
      Console.WriteLine("------ MyFunc ------")
      
      '// Retrieve standard 32-bit and 64-bit integer arguments directly
      Console.WriteLine(cb.ArgInt32(1))
      Console.WriteLine(cb.ArgInt64(2))
      
      '// Retrieve the value of a pointer argument by referencing its exact data type.
      Console.WriteLine(uc.ItemOf("Int8").DataType.ToString(cb.ArgAddr(3)))
      
      '// The Item object correctly identifies the type before conversion
      Console.WriteLine(uc.ItemOf("Int").DataType.ToString(cb.ArgPtr(4)))
   End Sub
   
   Public Sub MyFunction2(ByVal cb As uCalc.Callback)
      Dim uc = cb.uCalc
      Console.WriteLine("------ MyFunc2 ------")
      Console.WriteLine(uc.DataTypeOf(BuiltInType.Integer_8).ToString(cb.ArgPtr(1)))
   End Sub
   
   Public Sub MyFunction3(ByVal cb As uCalc.Callback)
      Dim uc = cb.uCalc
      Console.WriteLine("------ MyFunc3 ------")
      Console.WriteLine(uc.DataTypeOf(BuiltInType.Integer_16).ToString(cb.ArgPtr(1)))
   End Sub
   Public Sub Main()
      Dim uc As New uCalc()
      uc.DefineVariable("x As Int = 123") '// Int32
      uc.DefineVariable("xPtr As Int Ptr = AddressOf(x)")
      uc.DefineFunction("MyFunc(a As Int32, b As Int64, c As Byte, d As Int Ptr)", AddressOf MyFunction)
      uc.Eval("MyFunc(x*10, 1+1, 255, xPtr)")
      
      uc.DefineVariable("x2 As Int8 = -123")
      uc.DefineVariable("xPtr2 As Int8 Ptr = AddressOf(x2)")
      uc.DefineFunction("MyFunc2(d As Int8 Ptr)", AddressOf MyFunction2)
      uc.Eval("MyFunc2(xPtr2)")
      
      uc.DefineVariable("x3 As Int16 = 1234")
      uc.DefineVariable("xPtr3 As Int16 Ptr = AddressOf(x3)")
      uc.DefineFunction("MyFunc3(d As Int16 Ptr)", AddressOf MyFunction3)
      uc.Eval("MyFunc3(xPtr3)")
   End Sub
End Module
				
			
------ MyFunc ------
1230
2
-1
123
------ MyFunc2 ------
-123
------ MyFunc3 ------
1234
Determining properties of an expression part
				
					using uCalcSoftware;

var uc = new uCalc();

static void ItemCallback(uCalc.Callback cb) {
   Console.WriteLine($"Name: {cb.Item.Name}");
   Console.WriteLine($"Data type: {cb.Item.DataType.Name}");
   Console.WriteLine($"Param count: {cb.Item.Count}");
   Console.Write("Procedure type: ");
   if (cb.Item.IsProperty(ItemIs.Operator)) {
      Console.WriteLine("Operator");
   } else if (cb.Item.IsProperty(ItemIs.Function)) {
      Console.WriteLine("Function");
   }
   Console.WriteLine(cb.Item.Text);
   Console.WriteLine(cb.Item.Description);
   Console.WriteLine("---");
}


uc.DefineFunction("AAA() As Double", ItemCallback).Description = "Does this and that";
uc.DefineFunction("BBB(x, y, z) As String", ItemCallback).Description = "Does something else";
uc.DefineOperator("{x} CCC {y} As Int32", 0, Associativity.LeftToRight, ItemCallback);

uc.EvalStr("AAA()");
uc.EvalStr("BBB(9, 8, 7)");
uc.EvalStr("5 CCC 4");

				
			
Name: aaa
Data type: double
Param count: 0
Procedure type: Function
Function: AAA() As Double
Does this and that
---
Name: bbb
Data type: string
Param count: 3
Procedure type: Function
Function: BBB(x, y, z) As String
Does something else
---
Name: ccc
Data type: int
Param count: 2
Procedure type: Operator
Operator: {x} CCC {y} As Int32

---
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

void ucalc_call ItemCallback(uCalcBase::Callback cb) {
   cout << "Name: " << cb.Item().Name() << endl;
   cout << "Data type: " << cb.Item().DataType().Name() << endl;
   cout << "Param count: " << cb.Item().Count() << endl;
   cout << "Procedure type: ";
   if (cb.Item().IsProperty(ItemIs::Operator)) {
      cout << "Operator" << endl;
   } else if (cb.Item().IsProperty(ItemIs::Function)) {
      cout << "Function" << endl;
   }
   cout << cb.Item().Text() << endl;
   cout << cb.Item().Description() << endl;
   cout << "---" << endl;
}
int main() {
   uCalc uc;

   uc.DefineFunction("AAA() As Double", ItemCallback).Description("Does this and that");
   uc.DefineFunction("BBB(x, y, z) As String", ItemCallback).Description("Does something else");
   uc.DefineOperator("{x} CCC {y} As Int32", 0, Associativity::LeftToRight, ItemCallback);

   uc.EvalStr("AAA()");
   uc.EvalStr("BBB(9, 8, 7)");
   uc.EvalStr("5 CCC 4");

}
				
			
Name: aaa
Data type: double
Param count: 0
Procedure type: Function
Function: AAA() As Double
Does this and that
---
Name: bbb
Data type: string
Param count: 3
Procedure type: Function
Function: BBB(x, y, z) As String
Does something else
---
Name: ccc
Data type: int
Param count: 2
Procedure type: Operator
Operator: {x} CCC {y} As Int32

---
				
					Imports System
Imports uCalcSoftware
Public Module Program
   
   Public Sub ItemCallback(ByVal cb As uCalc.Callback)
      Console.WriteLine($"Name: {cb.Item.Name}")
      Console.WriteLine($"Data type: {cb.Item.DataType.Name}")
      Console.WriteLine($"Param count: {cb.Item.Count}")
      Console.Write("Procedure type: ")
      If cb.Item.IsProperty(ItemIs.Operator) Then
         Console.WriteLine("Operator")
         ElseIf cb.Item.IsProperty(ItemIs.Function ) Then
            Console.WriteLine("Function")
         End If
         Console.WriteLine(cb.Item.Text)
         Console.WriteLine(cb.Item.Description)
         Console.WriteLine("---")
      End Sub
      Public Sub Main()
         Dim uc As New uCalc()
         
         uc.DefineFunction("AAA() As Double", AddressOf ItemCallback).Description = "Does this and that"
         uc.DefineFunction("BBB(x, y, z) As String", AddressOf ItemCallback).Description = "Does something else"
         uc.DefineOperator("{x} CCC {y} As Int32", 0, Associativity.LeftToRight, AddressOf ItemCallback)
         
         uc.EvalStr("AAA()")
         uc.EvalStr("BBB(9, 8, 7)")
         uc.EvalStr("5 CCC 4")
         
      End Sub
   End Module
				
			
Name: aaa
Data type: double
Param count: 0
Procedure type: Function
Function: AAA() As Double
Does this and that
---
Name: bbb
Data type: string
Param count: 3
Procedure type: Function
Function: BBB(x, y, z) As String
Does something else
---
Name: ccc
Data type: int
Param count: 2
Procedure type: Operator
Operator: {x} CCC {y} As Int32

---