Ruby - cleanest way to return a value if truthy, or execute arbitrary code

I'm coding something in Ruby where, given a value foo output from a method call, I want to:

  • Return foo if foo is truthy
  • Log an error and return a default value if foo is falsy.

The simplest naive way to implement this is probably:

foo = procedure(input)

if foo
  foo
else
  log_error
  default
end

but this feels overly verbose because foo is repeated three times, and this style is very imperative.

What's the cleanest, most idiomatic way to write this?

(Performance matters-- let's assume that foo is truthy in the vast majority of cases.)


ANSWERS:


Living off of Ruby's Perl heritage:

foo = procedure(input) and return foo
log_error
default

This is a rare case where Ruby's anonymous block is actually useful:

foo = procedure(input) || begin
  log_error
  default
end

You can write that if log_error returns a true value

foo || log_error && default

If not:

foo || (log_error; default)

For the sake of completeness (and since no one has posted it yet) I'll add my original attempt at an answer:

procedure(input) || proc {
  log_error
  default
}.call

I can't think of any reason to use this over @mwp's answer:

procedure(input) || begin
  log_error
  default
end

because of the extra overhead (performance and readability) involved in creating the Proc object. Though some quick benchmarking reveals that the performance difference should be negligible in most cases, since the Proc object doesn't seem to be created unless procedure(input) is falsy.


All things considered, I would go with:

foo = procedure(input)
return foo if foo
log_error
default


 MORE:


 ? How can I set default values for an object's keys?
 ? Assigning to vs. from a slice
 ? Idiom to describe possibility of effect
 ? Interface implementation idioms
 ? Python: Idiom for interleaved lock acquisition
 ? Under the NVI idiom, why can't the virtual function be public?
 ? Haskell idiom for setting up a collection of indexed structured values
 ? Javascript Builder Pattern vs Options Object for contact importer
 ? Haskell Applicative idiom?
 ? most idiomatic way to structure a client side REST library?