merge
makes this very concise:
def create_hash(opt ={})
{
a: 0.40,
b: 0.30,
c: 0.05
}.merge(opt)
end
create_hash :a => 0.30
# => {:a=>0.3, :b=>0.3, :c=>0.05}
We use merge
in some of our in-house code to fine-tune configuration data. We have a global YAML file, then if we need to specify something different for a particular app or host, we have small YAML files containing just the hash data we need to modify. We merge the smaller hash with the global one and overwrite only the data that needs to change.
Looking at what you're doing:
hash = {:a => if opt[:a] ? a : 0.40; end},
:b => if opt[:b] ? b : 0.30; end,
:c => if opt[:c] ? c : 0.05; end}
There's a lot of confusion about how Ruby works. You'll immediately run into syntax errors:
opt = {}
hash = {:a => if opt[:a] ? a : 0.40; end},
:b => if opt[:b] ? b : 0.30; end,
:c => if opt[:c] ? c : 0.05; end}
# =>
# ~> -:3: syntax error, unexpected =>, expecting end-of-input
# ~> :b => if opt[:b] ? b : 0.30; end,
# ~> ^
That's because you can't:
- use a trailing conditional inside a hash assignment.
- end the first line with
},
which terminates the hash construction.
Cleaning up the indentation and removing the if
and end;...
:
opt = {}
hash = {
:a => opt[:a] ? a : 0.40,
:b => opt[:b] ? b : 0.30,
:c => opt[:c] ? c : 0.05
}
# => {:a=>0.4, :b=>0.3, :c=>0.05}
That'd work, however it's still got code smell because it's difficult to see what's really happening because of the ternary ("?:") statements. Ternary statements aren't inherently evil, but they can be harder to read, so use them sparingly, and always be aware that they can affect the clarity of the code.