in reply to creating operands

Sorry, even overload doesn't allow you to create new operators. A source filter is really your only option here.

The only other solution that comes to mind is the following:

sub definedor(&$) { defined($_[1]) ? $_[1] : $_[0]->() }

However, the usage is uglier than your original code:

definedor { $self->error('blah blah')) } $foo = $bar->id; # Ugly defined($foo = $bar->id) or $self->error('blah blah')); # Better