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: 

Fast Math Parser

Class: 

uCalcBase

Registers a callback function to dynamically format the string output of evaluated expressions.

Syntax

Format(OpCallback, string, DataType)

Parameters

callback
OpCallback
The user-defined callback function that receives the raw result and returns the formatted string.
targetDataTypeName
string
(Default = "")
The name of the data type this format applies to. Omit or pass an empty string to apply the format to all data types.
targetDataType
DataType
(Default = Empty)
A `DataType` object to target. This provides an alternative to specifying the data type by name.

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 targetDataTypeName and targetDataType parameters, 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 a DataType object, 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):

  1. The most recently added formatter is executed first.
  2. Its output is then passed as the input to the previously added formatter.
  3. 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
				
					#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;
}
				
			
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
				
			
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