var.visit

auto visit(handlers...)() scope const @safe

Apply a visitor pattern to this value, dispatching to the appropriate handler based on type.

This provides type-safe dispatch without manual switch on Type, similar to std.variant.visit. Handlers are provided as template arguments and can be lambdas, function pointers, or delegates.

Handler Selection:

  • Handlers accepting specific types (bool, long, double, string, var[], var[string]) are matched first.
  • A handler accepting var serves as a catch-all fallback.
  • If no matching handler is found for the current type, returns the default value of the return type.

Type Mapping:

  • NULL: matched by typeof(null) handler or fallback
  • BOOL: matched by bool handler
  • Integer types (BYTE..ULONG): matched by long handler (widened). ULONG values above long.max are matched by a ulong handler first; if only a long handler exists it sees the (wrapped) value through D's implicit conversion.
  • Floating types (FLOAT, DOUBLE, REAL): matched by double handler (widened)
  • STRING: matched by string handler
  • ARRAY: matched by var[] handler
  • OBJECT: matched by var[string] handler
  • Character types (CHAR, WCHAR, DCHAR): matched by dchar handler (widened)

Fallback normalization (documented behavior, intentional): the var-typed fallback does not receive the original receiver. It sees a normalized reboxed value following the same widening as typed handlers: narrow integer tags become LONG (a BYTE receiver arrives as LONG), FLOAT becomes DOUBLE, and characters may arrive reboxed after typed dispatch. A fallback handler therefore cannot inspect the receiver's original narrow tag and may not compare equal to the original under exact-tag equality. visitNogc shares the typed-handler widening. Because the fallback value is an independent copy (deep for const receivers), mutating it cannot affect the receiver.

Parameters

handlersOne or more callable handlers for different types.

Returns

The result of calling the matched handler, or R.init if no handler matches.

Examples

var v = 42;
string result = v.visit!(
   (long n) => "integer: " ~ n.to!string,
   (string s) => "string: " ~ s,
   (var fallback) => "other: " ~ fallback.toString()
);
assert(result == "integer: 42");

var s = "hello";
auto r = s.visit!(
   (long n) => n * 2,
   (string str) => cast(long)str.length
);
assert(r == 5); // length of "hello"