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.
Format(OpCallback, string, DataType)
Method
Product:
Class:
Registers a callback function to dynamically format the string output of evaluated expressions.
Syntax
Parameters
Return
Item
Returns an Item object representing the created format rule. This object can be used later to release the format.
Remarks
The Format() method allows you to intercept the output of functions like EvalStr and EvaluateStr and apply custom formatting transformations using a callback function. This creates a powerful, dynamic post-processing pipeline for all expression results.
Note: There are two versions of Format(). This one involves using a callback to a function in the host application for the formatting logic, while the other Format definition is done inline.
🎯 Targeting Specific Data Types
You can create formatters that apply globally or only to specific data types:
- Global Formatter: If you omit the
targetDataTypeNameandtargetDataTypeparameters, the callback will be applied to the string result of all data types. - Type-Specific Formatter: By providing a data type name (e.g.,
"Double") or aDataTypeobject, you can restrict the formatter to run only when the expression result matches that type. This is ideal for scenarios like formatting numbers as currency, dates into a specific layout, or booleans as "Yes/No".
📚 Layering and Execution Order (The Format Stack)
uCalc maintains a separate formatting pipeline for each data type (plus one for global formatters). When you add multiple formatters, they are pushed onto a stack. The execution order is Last-In, First-Out (LIFO):
- The most recently added formatter is executed first.
- Its output is then passed as the input to the previously added formatter.
- This continues until all applicable formatters in the stack have been processed.
This layering allows for building up complex formatting from simple, reusable components.
🗑️ Releasing Formats
This method returns an Item object. To remove the formatter from the pipeline, call uCalc.Item.Release on this item. This is crucial for temporary formatting rules to avoid memory leaks and unintended side effects.
Also, uCalc.EvalStr has a parameter that suppresses all formatting just for the given expression.
You can view all active formatters by using uc.ListOfItems(ItemIs.Format);.
🆚 Comparative Analysis
While languages like C# (string interpolation, String.Format) and Python (f-strings) provide excellent static formatting, uCalc's Format() method offers a different paradigm:
- Runtime Configuration: uCalc formatters are defined and layered at runtime. This allows an application to change its output style dynamically, perhaps based on user preferences or localization settings, without recompiling code.
- Decoupled Logic: The formatting logic is decoupled from the expression evaluation. You can define a complex calculation once and apply different formatting 'skins' to its output. This is highly effective for applications that need to present the same data in multiple ways (e.g., a report, a chart tooltip, a log file).
- Middleware Pipeline: The format stack acts like a middleware pipeline for strings, a concept more common in web frameworks. This is a uniquely powerful feature for a math parser, enabling sophisticated transformations that go far beyond simple value-to-string conversion.
Examples
Format using callback functions
using uCalcSoftware;
var uc = new uCalc();
static void OutputAnswerCB(uCalc.Callback cb) {
cb.ReturnStr("Answer: " + cb.ArgStr(1));
}
static void OutputSymbolCB(uCalc.Callback cb) {
cb.ReturnStr("==> " + cb.ArgStr(1));
}
static void OutputBoolCB(uCalc.Callback cb) {
if (cb.ArgStr(1) == "false") {
cb.ReturnStr("No");
} else if (cb.ArgStr(1) == "true") {
cb.ReturnStr("Yes");
}
}
// This format inserts "Answer: " in front of every result
var OutputAnswer = uc.Format( OutputAnswerCB);
Console.WriteLine(uc.EvalStr("10+20"));
Console.WriteLine(uc.EvalStr("'Hello '+'world'"));
Console.WriteLine(uc.EvalStr("5 > 10"));
Console.WriteLine("---");
// This one inserts ==> in front of the result
// The previously defined "Answer: " output is still prepended as well
var OutputSymbol = uc.Format( OutputSymbolCB);
Console.WriteLine(uc.EvalStr("10+20"));
Console.WriteLine(uc.EvalStr("'Hello '+'world'"));
Console.WriteLine(uc.EvalStr("5 > 10"));
Console.WriteLine("---");
// Causes Boolean values to return Yes or No (instead of true or false)
var OutputBool = uc.Format( OutputBoolCB, "Bool");
Console.WriteLine(uc.EvalStr("10+20"));
Console.WriteLine(uc.EvalStr("'Hello '+'world'"));
Console.WriteLine(uc.EvalStr("5 > 10"));
Console.WriteLine(uc.EvalStr("5 < 10"));
Console.WriteLine("---");
// The previously defined "==>" output is removed
OutputSymbol.Release();
Console.WriteLine(uc.EvalStr("10+20"));
Console.WriteLine(uc.EvalStr("'Hello '+'world'"));
Console.WriteLine(uc.EvalStr("5 > 10"));
Console.WriteLine(uc.EvalStr("5 < 10"));
Answer: 30
Answer: Hello world
Answer: false
---
Answer: ==> 30
Answer: ==> Hello world
Answer: ==> false
---
Answer: ==> 30
Answer: ==> Hello world
Answer: ==> No
Answer: ==> Yes
---
Answer: 30
Answer: Hello world
Answer: No
Answer: Yes using uCalcSoftware; var uc = new uCalc(); static void OutputAnswerCB(uCalc.Callback cb) { cb.ReturnStr("Answer: " + cb.ArgStr(1)); } static void OutputSymbolCB(uCalc.Callback cb) { cb.ReturnStr("==> " + cb.ArgStr(1)); } static void OutputBoolCB(uCalc.Callback cb) { if (cb.ArgStr(1) == "false") { cb.ReturnStr("No"); } else if (cb.ArgStr(1) == "true") { cb.ReturnStr("Yes"); } } // This format inserts "Answer: " in front of every result var OutputAnswer = uc.Format( OutputAnswerCB); Console.WriteLine(uc.EvalStr("10+20")); Console.WriteLine(uc.EvalStr("'Hello '+'world'")); Console.WriteLine(uc.EvalStr("5 > 10")); Console.WriteLine("---"); // This one inserts ==> in front of the result // The previously defined "Answer: " output is still prepended as well var OutputSymbol = uc.Format( OutputSymbolCB); Console.WriteLine(uc.EvalStr("10+20")); Console.WriteLine(uc.EvalStr("'Hello '+'world'")); Console.WriteLine(uc.EvalStr("5 > 10")); Console.WriteLine("---"); // Causes Boolean values to return Yes or No (instead of true or false) var OutputBool = uc.Format( OutputBoolCB, "Bool"); Console.WriteLine(uc.EvalStr("10+20")); Console.WriteLine(uc.EvalStr("'Hello '+'world'")); Console.WriteLine(uc.EvalStr("5 > 10")); Console.WriteLine(uc.EvalStr("5 < 10")); Console.WriteLine("---"); // The previously defined "==>" output is removed OutputSymbol.Release(); Console.WriteLine(uc.EvalStr("10+20")); Console.WriteLine(uc.EvalStr("'Hello '+'world'")); Console.WriteLine(uc.EvalStr("5 > 10")); Console.WriteLine(uc.EvalStr("5 < 10"));
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
void ucalc_call OutputAnswerCB(uCalcBase::Callback cb) {
cb.ReturnStr("Answer: " + cb.ArgStr(1));
}
void ucalc_call OutputSymbolCB(uCalcBase::Callback cb) {
cb.ReturnStr("==> " + cb.ArgStr(1));
}
void ucalc_call OutputBoolCB(uCalcBase::Callback cb) {
if (cb.ArgStr(1) == "false") {
cb.ReturnStr("No");
} else if (cb.ArgStr(1) == "true") {
cb.ReturnStr("Yes");
}
}
int main() {
uCalc uc;
// This format inserts "Answer: " in front of every result
auto OutputAnswer = uc.Format( OutputAnswerCB);
cout << uc.EvalStr("10+20") << endl;
cout << uc.EvalStr("'Hello '+'world'") << endl;
cout << uc.EvalStr("5 > 10") << endl;
cout << "---" << endl;
// This one inserts ==> in front of the result
// The previously defined "Answer: " output is still prepended as well
auto OutputSymbol = uc.Format( OutputSymbolCB);
cout << uc.EvalStr("10+20") << endl;
cout << uc.EvalStr("'Hello '+'world'") << endl;
cout << uc.EvalStr("5 > 10") << endl;
cout << "---" << endl;
// Causes Boolean values to return Yes or No (instead of true or false)
auto OutputBool = uc.Format( OutputBoolCB, "Bool");
cout << uc.EvalStr("10+20") << endl;
cout << uc.EvalStr("'Hello '+'world'") << endl;
cout << uc.EvalStr("5 > 10") << endl;
cout << uc.EvalStr("5 < 10") << endl;
cout << "---" << endl;
// The previously defined "==>" output is removed
OutputSymbol.Release();
cout << uc.EvalStr("10+20") << endl;
cout << uc.EvalStr("'Hello '+'world'") << endl;
cout << uc.EvalStr("5 > 10") << endl;
cout << uc.EvalStr("5 < 10") << endl;
}
Answer: 30
Answer: Hello world
Answer: false
---
Answer: ==> 30
Answer: ==> Hello world
Answer: ==> false
---
Answer: ==> 30
Answer: ==> Hello world
Answer: ==> No
Answer: ==> Yes
---
Answer: 30
Answer: Hello world
Answer: No
Answer: Yes #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; void ucalc_call OutputAnswerCB(uCalcBase::Callback cb) { cb.ReturnStr("Answer: " + cb.ArgStr(1)); } void ucalc_call OutputSymbolCB(uCalcBase::Callback cb) { cb.ReturnStr("==> " + cb.ArgStr(1)); } void ucalc_call OutputBoolCB(uCalcBase::Callback cb) { if (cb.ArgStr(1) == "false") { cb.ReturnStr("No"); } else if (cb.ArgStr(1) == "true") { cb.ReturnStr("Yes"); } } int main() { uCalc uc; // This format inserts "Answer: " in front of every result auto OutputAnswer = uc.Format( OutputAnswerCB); cout << uc.EvalStr("10+20") << endl; cout << uc.EvalStr("'Hello '+'world'") << endl; cout << uc.EvalStr("5 > 10") << endl; cout << "---" << endl; // This one inserts ==> in front of the result // The previously defined "Answer: " output is still prepended as well auto OutputSymbol = uc.Format( OutputSymbolCB); cout << uc.EvalStr("10+20") << endl; cout << uc.EvalStr("'Hello '+'world'") << endl; cout << uc.EvalStr("5 > 10") << endl; cout << "---" << endl; // Causes Boolean values to return Yes or No (instead of true or false) auto OutputBool = uc.Format( OutputBoolCB, "Bool"); cout << uc.EvalStr("10+20") << endl; cout << uc.EvalStr("'Hello '+'world'") << endl; cout << uc.EvalStr("5 > 10") << endl; cout << uc.EvalStr("5 < 10") << endl; cout << "---" << endl; // The previously defined "==>" output is removed OutputSymbol.Release(); cout << uc.EvalStr("10+20") << endl; cout << uc.EvalStr("'Hello '+'world'") << endl; cout << uc.EvalStr("5 > 10") << endl; cout << uc.EvalStr("5 < 10") << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub OutputAnswerCB(ByVal cb As uCalc.Callback)
cb.ReturnStr("Answer: " + cb.ArgStr(1))
End Sub
Public Sub OutputSymbolCB(ByVal cb As uCalc.Callback)
cb.ReturnStr("==> " + cb.ArgStr(1))
End Sub
Public Sub OutputBoolCB(ByVal cb As uCalc.Callback)
If cb.ArgStr(1) = "false" Then
cb.ReturnStr("No")
ElseIf cb.ArgStr(1) = "true" Then
cb.ReturnStr("Yes")
End If
End Sub
Public Sub Main()
Dim uc As New uCalc()
'// This format inserts "Answer: " in front of every result
Dim OutputAnswer = uc.Format(AddressOf OutputAnswerCB)
Console.WriteLine(uc.EvalStr("10+20"))
Console.WriteLine(uc.EvalStr("'Hello '+'world'"))
Console.WriteLine(uc.EvalStr("5 > 10"))
Console.WriteLine("---")
'// This one inserts ==> in front of the result
'// The previously defined "Answer: " output is still prepended as well
Dim OutputSymbol = uc.Format(AddressOf OutputSymbolCB)
Console.WriteLine(uc.EvalStr("10+20"))
Console.WriteLine(uc.EvalStr("'Hello '+'world'"))
Console.WriteLine(uc.EvalStr("5 > 10"))
Console.WriteLine("---")
'// Causes Boolean values to return Yes or No (instead of true or false)
Dim OutputBool = uc.Format(AddressOf OutputBoolCB, "Bool")
Console.WriteLine(uc.EvalStr("10+20"))
Console.WriteLine(uc.EvalStr("'Hello '+'world'"))
Console.WriteLine(uc.EvalStr("5 > 10"))
Console.WriteLine(uc.EvalStr("5 < 10"))
Console.WriteLine("---")
'// The previously defined "==>" output is removed
OutputSymbol.Release()
Console.WriteLine(uc.EvalStr("10+20"))
Console.WriteLine(uc.EvalStr("'Hello '+'world'"))
Console.WriteLine(uc.EvalStr("5 > 10"))
Console.WriteLine(uc.EvalStr("5 < 10"))
End Sub
End Module
Answer: 30
Answer: Hello world
Answer: false
---
Answer: ==> 30
Answer: ==> Hello world
Answer: ==> false
---
Answer: ==> 30
Answer: ==> Hello world
Answer: ==> No
Answer: ==> Yes
---
Answer: 30
Answer: Hello world
Answer: No
Answer: Yes Imports System Imports uCalcSoftware Public Module Program Public Sub OutputAnswerCB(ByVal cb As uCalc.Callback) cb.ReturnStr("Answer: " + cb.ArgStr(1)) End Sub Public Sub OutputSymbolCB(ByVal cb As uCalc.Callback) cb.ReturnStr("==> " + cb.ArgStr(1)) End Sub Public Sub OutputBoolCB(ByVal cb As uCalc.Callback) If cb.ArgStr(1) = "false" Then cb.ReturnStr("No") ElseIf cb.ArgStr(1) = "true" Then cb.ReturnStr("Yes") End If End Sub Public Sub Main() Dim uc As New uCalc() '// This format inserts "Answer: " in front of every result Dim OutputAnswer = uc.Format(AddressOf OutputAnswerCB) Console.WriteLine(uc.EvalStr("10+20")) Console.WriteLine(uc.EvalStr("'Hello '+'world'")) Console.WriteLine(uc.EvalStr("5 > 10")) Console.WriteLine("---") '// This one inserts ==> in front of the result '// The previously defined "Answer: " output is still prepended as well Dim OutputSymbol = uc.Format(AddressOf OutputSymbolCB) Console.WriteLine(uc.EvalStr("10+20")) Console.WriteLine(uc.EvalStr("'Hello '+'world'")) Console.WriteLine(uc.EvalStr("5 > 10")) Console.WriteLine("---") '// Causes Boolean values to return Yes or No (instead of true or false) Dim OutputBool = uc.Format(AddressOf OutputBoolCB, "Bool") Console.WriteLine(uc.EvalStr("10+20")) Console.WriteLine(uc.EvalStr("'Hello '+'world'")) Console.WriteLine(uc.EvalStr("5 > 10")) Console.WriteLine(uc.EvalStr("5 < 10")) Console.WriteLine("---") '// The previously defined "==>" output is removed OutputSymbol.Release() Console.WriteLine(uc.EvalStr("10+20")) Console.WriteLine(uc.EvalStr("'Hello '+'world'")) Console.WriteLine(uc.EvalStr("5 > 10")) Console.WriteLine(uc.EvalStr("5 < 10")) End Sub End Module