EDIT: Technically a && a.upcase, but that’s not very common and #try is simpler to grok.
EDIT2: It’s also usually ideal if you can just remove Nil from the type of a variable entirely. However depending on your use case/context this may not ofc be possible.
Yes, I try to avoid nil as much as possible but when it comes to external data it’s sometimes impossible.
For example, if in this YAML data I don’t know if the keys foo, bar and baz are present, the try chain become quite long:
data = YAML.parse <<-YAML
pp data["foo"]?.try &.["bar"]?.try &.["baz"]?.try &..as_s
Do you know what the data structure is ahead of time? Like its schema? You’d have to know what you’re parsing and it’s possible those keys would always be there? Like in your example there’s no reason to check if foo, bar, and baz are nil since they’re clearly not?
I’d recommend defining your own types using YAML::Serializable:
getter foo : Foo
getter bar : Bar
getter baz : Array(String)
yaml = <<-YAML
data = Data.from_yaml(yaml) # => Data(@foo=Foo(@bar=Bar(@baz=["qux", "fox"])))
data.foo.bar.baz # => "fox"
And from_yaml will throw an error if the YAML doesn’t match the classes you’re mapping it into, so you’ve basically validated that you have what you need in a single line of code. Simplifes the code that comes after.