uCalc API Version: 5.7.0-preview.1 Released: 7/30/2026
Warning
uCalc API Preview Release Notice:This preview documentation describes the intended behavior of the API. It is not fully accurate or complete.The current preview build contains incomplete features, unoptimized performance, and is subject to breaking changes.Use of the preview version in your production code is not recommended.
Explains how the ByHandle parameter modifier enables metaprogramming in callbacks by passing an argument's underlying metadata object.
ByHandleWhile most functions operate on values, some of the most powerful programming techniques involve operating on the code itself. This is called metaprogramming. In uCalc, the ByHandle parameter modifier is the key that unlocks this capability, allowing your callbacks to inspect the properties of the arguments they receive, not just their final values.
To understand ByHandle, it's useful to compare it with the other argument modifiers:
ByVal (Default): Passes the argument's final, computed value. This is standard behavior.ByExpr: Passes the argument as an unevaluated Expression object, representing the code itself. This is used for lazy evaluation.ByHandle: Passes the argument's underlying Item object, representing its metadata. This is used for introspection.Item Handle?When a parameter is marked with ByHandle, your callback doesn't receive a simple number or string. Instead, it receives a handle to the argument's internal Item object, which you can retrieve with cb.ArgItem(). This object is a rich container of metadata, allowing you to ask questions about the argument, such as:
item.Name())item.DataType())item.IsProperty(ItemIs::Variable))item.ValueStr())item.ValueAddr())This ability to inspect an argument before deciding what to do with it is the essence of metaprogramming in uCalc.
Print function that can accept and correctly display any number of arguments of any type by inspecting each one.AssertIsVariable(arg) function could raise an error if the user passes a literal value like 5 instead of a variable name.Swap function.vs. C# Reflection (MethodInfo, ParameterInfo): While C# has powerful reflection capabilities, they are often complex and operate on compile-time constructs. uCalc's ByHandle provides a lightweight, runtime-focused alternative that is deeply integrated into the callback model. Retrieving an argument's metadata is a simple method call, not a complex traversal of Type and Assembly objects.
vs. Dynamic Languages (Python/JavaScript): Languages like Python have rich introspection tools (e.g., the inspect module). ByHandle brings this dynamic power into a strongly-typed host environment (C#/C++), offering a unique combination of flexibility and performance. It allows you to build functions that are as dynamic as a Python script but run with the speed of compiled C++ code.
ID: 1236
using uCalcSoftware;
var uc = new uCalc();
static void DescribeArg(uCalc.Callback cb) {
// Retrieve the Item object for the first argument.
var item = cb.ArgItem(1);
// Inspect the item's metadata.
var name = item.Name;
if (name == "") {
name = "(literal)";
}
Console.WriteLine($" - Name: {name}, Type: {item.DataType.Name}");
}
uc.DefineFunction("Describe(ByHandle arg As AnyType)", DescribeArg);
uc.DefineVariable("my_var = 100");
Console.WriteLine("Inspecting a variable:");
uc.Eval("Describe(my_var)");
Console.WriteLine("Inspecting a literal value:");
uc.Eval("Describe(123.45)");
Console.WriteLine("Inspecting a string value:");
uc.EvalStr("Describe('abc xyz')");
Inspecting a variable:
- Name: my_var, Type: double
Inspecting a literal value:
- Name: (literal), Type: double
Inspecting a string value:
- Name: (literal), Type: string using uCalcSoftware; var uc = new uCalc(); static void DescribeArg(uCalc.Callback cb) { // Retrieve the Item object for the first argument. var item = cb.ArgItem(1); // Inspect the item's metadata. var name = item.Name; if (name == "") { name = "(literal)"; } Console.WriteLine($" - Name: {name}, Type: {item.DataType.Name}"); } uc.DefineFunction("Describe(ByHandle arg As AnyType)", DescribeArg); uc.DefineVariable("my_var = 100"); Console.WriteLine("Inspecting a variable:"); uc.Eval("Describe(my_var)"); Console.WriteLine("Inspecting a literal value:"); uc.Eval("Describe(123.45)"); Console.WriteLine("Inspecting a string value:"); uc.EvalStr("Describe('abc xyz')");
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
void ucalc_call DescribeArg(uCalcBase::Callback cb) {
// Retrieve the Item object for the first argument.
auto item = cb.ArgItem(1);
// Inspect the item's metadata.
auto name = item.Name();
if (name == "") {
name = "(literal)";
}
cout << " - Name: " << name << ", Type: " << item.DataType().Name() << endl;
}
int main() {
uCalc uc;
uc.DefineFunction("Describe(ByHandle arg As AnyType)", DescribeArg);
uc.DefineVariable("my_var = 100");
cout << "Inspecting a variable:" << endl;
uc.Eval("Describe(my_var)");
cout << "Inspecting a literal value:" << endl;
uc.Eval("Describe(123.45)");
cout << "Inspecting a string value:" << endl;
uc.EvalStr("Describe('abc xyz')");
}
Inspecting a variable:
- Name: my_var, Type: double
Inspecting a literal value:
- Name: (literal), Type: double
Inspecting a string value:
- Name: (literal), Type: string #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; void ucalc_call DescribeArg(uCalcBase::Callback cb) { // Retrieve the Item object for the first argument. auto item = cb.ArgItem(1); // Inspect the item's metadata. auto name = item.Name(); if (name == "") { name = "(literal)"; } cout << " - Name: " << name << ", Type: " << item.DataType().Name() << endl; } int main() { uCalc uc; uc.DefineFunction("Describe(ByHandle arg As AnyType)", DescribeArg); uc.DefineVariable("my_var = 100"); cout << "Inspecting a variable:" << endl; uc.Eval("Describe(my_var)"); cout << "Inspecting a literal value:" << endl; uc.Eval("Describe(123.45)"); cout << "Inspecting a string value:" << endl; uc.EvalStr("Describe('abc xyz')"); }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub DescribeArg(ByVal cb As uCalc.Callback)
'// Retrieve the Item object for the first argument.
Dim item = cb.ArgItem(1)
'// Inspect the item's metadata.
Dim name = item.Name
If Len(name) = 0 Then
name = "(literal)"
End If
Console.WriteLine($" - Name: {name}, Type: {item.DataType.Name}")
End Sub
Public Sub Main()
Dim uc As New uCalc()
uc.DefineFunction("Describe(ByHandle arg As AnyType)", AddressOf DescribeArg)
uc.DefineVariable("my_var = 100")
Console.WriteLine("Inspecting a variable:")
uc.Eval("Describe(my_var)")
Console.WriteLine("Inspecting a literal value:")
uc.Eval("Describe(123.45)")
Console.WriteLine("Inspecting a string value:")
uc.EvalStr("Describe('abc xyz')")
End Sub
End Module
Inspecting a variable:
- Name: my_var, Type: double
Inspecting a literal value:
- Name: (literal), Type: double
Inspecting a string value:
- Name: (literal), Type: string Imports System Imports uCalcSoftware Public Module Program Public Sub DescribeArg(ByVal cb As uCalc.Callback) '// Retrieve the Item object for the first argument. Dim item = cb.ArgItem(1) '// Inspect the item's metadata. Dim name = item.Name If Len(name) = 0 Then name = "(literal)" End If Console.WriteLine($" - Name: {name}, Type: {item.DataType.Name}") End Sub Public Sub Main() Dim uc As New uCalc() uc.DefineFunction("Describe(ByHandle arg As AnyType)", AddressOf DescribeArg) uc.DefineVariable("my_var = 100") Console.WriteLine("Inspecting a variable:") uc.Eval("Describe(my_var)") Console.WriteLine("Inspecting a literal value:") uc.Eval("Describe(123.45)") Console.WriteLine("Inspecting a string value:") uc.EvalStr("Describe('abc xyz')") End Sub End Module
ID: 1237
using uCalcSoftware;
var uc = new uCalc();
static void PrintGeneric(uCalc.Callback cb) {
string output = "";
var i = 0;
for ( i = 1; i <= cb.ArgCount(); i++) {
// Get the item and retrieve its value as a string.
var item = cb.ArgItem(i);
output = output + item.ValueStr();
if (i < cb.ArgCount()) {
output = output + ", ";
}
}
Console.WriteLine(output);
}
// Define a variadic function that accepts any number of arguments ByHandle.
uc.DefineFunction("Print(ByHandle args As AnyType...)", PrintGeneric);
uc.Eval("Print('User:', 'Alice', 'ID:', 101, 'Status:', true)");
User:, Alice, ID:, 101, Status:, true using uCalcSoftware; var uc = new uCalc(); static void PrintGeneric(uCalc.Callback cb) { string output = ""; var i = 0; for ( i = 1; i <= cb.ArgCount(); i++) { // Get the item and retrieve its value as a string. var item = cb.ArgItem(i); output = output + item.ValueStr(); if (i < cb.ArgCount()) { output = output + ", "; } } Console.WriteLine(output); } // Define a variadic function that accepts any number of arguments ByHandle. uc.DefineFunction("Print(ByHandle args As AnyType...)", PrintGeneric); uc.Eval("Print('User:', 'Alice', 'ID:', 101, 'Status:', true)");
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
void ucalc_call PrintGeneric(uCalcBase::Callback cb) {
string output = "";
auto i = 0;
for ( i = 1; i <= cb.ArgCount(); i++) {
// Get the item and retrieve its value as a string.
auto item = cb.ArgItem(i);
output = output + item.ValueStr();
if (i < cb.ArgCount()) {
output = output + ", ";
}
}
cout << output << endl;
}
int main() {
uCalc uc;
// Define a variadic function that accepts any number of arguments ByHandle.
uc.DefineFunction("Print(ByHandle args As AnyType...)", PrintGeneric);
uc.Eval("Print('User:', 'Alice', 'ID:', 101, 'Status:', true)");
}
User:, Alice, ID:, 101, Status:, true #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; void ucalc_call PrintGeneric(uCalcBase::Callback cb) { string output = ""; auto i = 0; for ( i = 1; i <= cb.ArgCount(); i++) { // Get the item and retrieve its value as a string. auto item = cb.ArgItem(i); output = output + item.ValueStr(); if (i < cb.ArgCount()) { output = output + ", "; } } cout << output << endl; } int main() { uCalc uc; // Define a variadic function that accepts any number of arguments ByHandle. uc.DefineFunction("Print(ByHandle args As AnyType...)", PrintGeneric); uc.Eval("Print('User:', 'Alice', 'ID:', 101, 'Status:', true)"); }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub PrintGeneric(ByVal cb As uCalc.Callback)
Dim output As String = ""
Dim i = 0
For i = 1 To cb.ArgCount()
'// Get the item and retrieve its value as a string.
Dim item = cb.ArgItem(i)
output = output + item.ValueStr()
If i < cb.ArgCount() Then
output = output + ", "
End If
Next
Console.WriteLine(output)
End Sub
Public Sub Main()
Dim uc As New uCalc()
'// Define a variadic function that accepts any number of arguments ByHandle.
uc.DefineFunction("Print(ByHandle args As AnyType...)", AddressOf PrintGeneric)
uc.Eval("Print('User:', 'Alice', 'ID:', 101, 'Status:', true)")
End Sub
End Module
User:, Alice, ID:, 101, Status:, true Imports System Imports uCalcSoftware Public Module Program Public Sub PrintGeneric(ByVal cb As uCalc.Callback) Dim output As String = "" Dim i = 0 For i = 1 To cb.ArgCount() '// Get the item and retrieve its value as a string. Dim item = cb.ArgItem(i) output = output + item.ValueStr() If i < cb.ArgCount() Then output = output + ", " End If Next Console.WriteLine(output) End Sub Public Sub Main() Dim uc As New uCalc() '// Define a variadic function that accepts any number of arguments ByHandle. uc.DefineFunction("Print(ByHandle args As AnyType...)", AddressOf PrintGeneric) uc.Eval("Print('User:', 'Alice', 'ID:', 101, 'Status:', true)") End Sub End Module