I agree that it could be convenient in some situations, but it can be implemented without changes to some languages. Here's a quick example in C#:
(keep in mind that these examples are contrived, and in this situation it'd be much cleaner to do Console.WriteLine(t == null ? "" : (t.ToString() ?? ""))
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Thing t = null;
// t is null so the fail delegate is called
Console.WriteLine(InlineTryCatch(()=> t.ToString(), ()=> "Fail 1 (OK)"));
// t is null, but there's no fail so default(T) is returned
Console.WriteLine(InlineTryCatch(() => t.ToString(), null));
// t is null and a NullReferenceException is thrown. That's the one we're looking for, so fail delegate is called
Console.WriteLine(InlineTryCatch<string, NullReferenceException>(() => t.ToString(), (ex) => "Fail 2 (OK)"));
try
{
// t is null, but the exception thrown doesn't match. because it's not a matching exception
// the exception is rethrown
Console.WriteLine(InlineTryCatch<string, IndexOutOfRangeException>(() => t.ToString(), (ex) => "Fail 3 (OK)"));
}
catch
{
Console.WriteLine("Exception 1");
}
// no exception so the success delegate is called
t = new Thing();
Console.WriteLine(InlineTryCatch(() => t.ToString(), () => "fail 4"));
}
class Thing
{
public override string ToString()
{
return "Win!";
}
}
static T InlineTryCatch<T, U>(Func<T> func, Func<U, T> fail) where U : Exception
{
try
{
return func();
}
catch (U ex)
{
if (fail != null)
{
return fail(ex);
}
else
{
throw ex;
}
}
}
static T InlineTryCatch<T>(Func<T> func, Func<T> fail)
{
return InlineTryCatch<T, Exception>(func, (ex) => fail == null ? default(T) : fail());
}
}
}