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.
ArgExpr
Method
Product:
Class:
Retrieves an argument passed by expression, allowing for lazy evaluation within a callback.
Syntax
Parameters
Return
Expression
Returns the unevaluated Expression object passed as an argument. The callback can then choose to evaluate it, inspect it, or ignore it.
Remarks
⚙️ How It Works
The ArgExpr method is the key to lazy evaluation in uCalc. It retrieves an argument that was passed not as a final value, but as a raw, unevaluated Expression object. This is accomplished by marking a parameter with the ByExpr modifier in its DefineFunction signature.
uc.DefineFunction("MyFunc(ByExpr formula)", MyCallback);
Inside the MyCallback function, calling cb.ArgExpr(1) retrieves the parsed expression tree for whatever argument was passed to formula. The callback then has complete control over when and if that expression is ever evaluated by calling .Evaluate() on the returned object.
💡 The Power of Lazy Evaluation
Passing expressions instead of values unlocks several advanced capabilities:
Short-Circuiting Logic: You can create functions that only evaluate the arguments they need. The most common example is a custom
IIffunction, which evaluates either thethenor theelseexpression, but never both. This prevents side effects and errors (like division by zero) in the unevaluated branch.Custom Control Structures:
ByExprenables you to build your own looping and aggregation functions. The callback can evaluate the same expression multiple times with different variable values, effectively creating customforloops orsumfunctions directly within the uCalc engine.Metaprogramming: Because you receive an
Expressionobject, your callback can inspect the argument's raw text viamyExpr.Str()before deciding to execute it. This allows for powerful pre-evaluation validation, transformation, or logging.
🆚 Comparative Analysis
vs. C# Delegates/Lambdas: Passing an expression with
ByExpris conceptually similar to passing aFunc<T>delegate in C#. Both techniques pass a piece of code to be executed later. However, uCalc's approach is designed for dynamic, string-based scripting environments where you can't compile a lambda ahead of time. The ability to inspect the expression's text also gives it a metaprogramming advantage over standard delegates.vs. C++ Function Pointers: While also a way to pass executable logic,
ByExpris a much higher-level and safer construct. The entire lifecycle of the Expression object is managed by the uCalc engine, avoiding the complexities of manual memory management associated with raw function pointers.
Examples
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 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)"));
#include
#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 #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; }
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 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