tryCall<T, A extends Object?> method

T? tryCall<T, A extends Object?>(
  1. List<A>? positionalArguments, [
  2. Map<Symbol, A>? namedArguments
])

Invokes the function dynamically, returning null if it throws an exception.

This method uses Function.apply to call the function with a given set of positionalArguments and namedArguments.

The generic type <A> can be specified if all arguments are of the same type, but it defaults to dynamic to support functions with mixed-type arguments (e.g., (String, int)).

{@tool snippet}

void main() {
  // --- Example 1: Function with a single argument type ---
  String repeat(String s, int times) => s * times;

  // Here we could specify `<Object>` or the default `<dynamic>`.
  final result1 = repeat.tryCall<String>(['Hello ', 2]);
  print(result1); // Prints: Hello Hello


  // --- Example 2: Function with named arguments ---
  String greet({required String name, String title = 'Dr.'}) => '$title $name';

  final result2 = greet.tryCall<String>([], {#name: 'Alice', #title: 'Ms.'});
  print(result2); // Prints: Ms. Alice


  // --- Example 3: Failure case ---
  int parseInt(String s) => int.parse(s);

  // Throws FormatException, which is caught and returns null.
  final result3 = parseInt.tryCall<int>(['not a number']);
  print(result3); // Prints: null
}

{@end-tool}

Implementation

T? tryCall<T, A extends Object?>(
  List<A>? positionalArguments, [
  Map<Symbol, A>? namedArguments,
]) {
  try {
    // Function.apply expects List<dynamic>, so we pass the args as-is.
    // The generic <A> provides compile-time checking for the caller.
    return Function.apply(
      this,
      positionalArguments ?? [],
      namedArguments ?? {},
    ) as T?;
  } on TypeError catch (_) {
    // Wrong types / return-cast failure → expected absorption.
    return null;
  } on NoSuchMethodError catch (_) {
    // Wrong arity or missing named arg → expected absorption.
    return null;
  } on Exception catch (_) {
    // The callee threw something domain-level (FormatException, etc.) →
    // expected absorption.
    return null;
  }
  // Critical `Error` subtypes (StackOverflowError, OutOfMemoryError,
  // AssertionError, StateError, ...) intentionally fall through. Catching
  // them would mask program-state corruption that a medical-grade caller
  // *must* see — silent absorption of those is more dangerous than the
  // missing convenience.
}