uCalc API Version: 2.1.3-preview.2 Released: 6/17/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: 

Fast Math Parser

Class: 

Callback

Retrieves an argument passed by expression, allowing for lazy evaluation within a callback.

Syntax

ArgExpr(int)

Parameters

index
int
The 1-based index of the argument to retrieve.

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 IIf function, which evaluates either the then or the else expression, but never both. This prevents side effects and errors (like division by zero) in the unevaluated branch.

  • Custom Control Structures: ByExpr enables you to build your own looping and aggregation functions. The callback can evaluate the same expression multiple times with different variable values, effectively creating custom for loops or sum functions directly within the uCalc engine.

  • Metaprogramming: Because you receive an Expression object, your callback can inspect the argument's raw text via myExpr.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 ByExpr is conceptually similar to passing a Func<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, ByExpr is 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
				
					#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