Purpose

This include file provides a value-or-error return type for MQL5, so functions can report success or failure explicitly instead of through the global GetLastError() / ResetLastError() state — which is easy to forget, easy to overwrite, and forces out-parameters and "magic" return values.

What it does

 A function returns one object that either holds a value or an Error; the caller must check before using the value.

  • ResultValue  — for value types (numbers, structs).
  • Result  — the same contract for objects held by pointer (classes).
  • Error  — a lightweight struct (code + description); codes map to readable names via EnumToString.
  • MQLError  — a thin wrapper over GetLastError / ResetLastError / SetUserError.
  • Macros —  TRY ,  RETURN_ON_ERROR ,  PRINT_ON_ERROR ,  RETURN_SAME_ON_ERROR ,  RESULT_ON_ERROR  — for early-return propagation without boilerplate.
  • Optional callbacks —  Then ,  Match ,  MapError  (they take top-level or static functions; MQL5 has no closures).

Accessors:  Value() ,  ValueOr(fallback) ,  CurrentError() ,  IsError() .

Usage

// Stage functions (top-level — MQL5 has no closures)
ResultValue<double> EnsurePositive(const double &value)
{
   if (value <= 0.0)
   {
      return ResultValue<double>::Fail("price must be positive");
   }
   return ResultValue<double>::Ok(value);
}

ResultValue<double> ToPips(const double &price)
{
   return ResultValue<double>::Ok(price / _Point);
}

Error Describe(const Error &error)
{
   return Error::Create(error.code, "pipeline failed: " + error.description);
}

void OnOk(const double &value)  { PrintFormat("[pipeline] result = %.1f pips", value); }
void OnFail(const Error &error) { PrintFormat("[pipeline] %s", error.description); }

// The pipeline: read -> validate -> transform -> (annotate error) -> handle
void RunPipeline()
{
   SymbolDouble("EURUSD", SYMBOL_BID)
      .Then(EnsurePositive)
      .Then(ToPips)
      .MapError(Describe)
      .Match(OnOk, OnFail);
}