The Crystal Programming Language Forum

What is a good way to deal with objects that can be nil?

I am looking for recommendations for good ways to use objects that can be nil. I know about not_nil!. But that can throw error during runtime. So I am looking for something that I can deal with if the object is actually nil, so that no runtime exceptions are thrown.

Here I read that one could use try, but that is not working for me. Here is the example where it is failing.

def ret_nilable(n)
    if n % 2 == 0
        return {v1: 1, v2: 2}
    else
        return nil
    end
end

If I try:

5.times do |n|
    val = retnilable(n)[:v1]?.try {|x| x} 
    puts "#{n}: #{val}"
end

Does not work. compiler says undefined method '[]?' for Nil

I also tried

5.times do |n|
    val = retnilable(n)?.try {|rec| rec}
    puts "#{n}: #{val}"
end

Does not work. compiler says unexpected token: .
Any suggestions? Thank you.

You need to apply .try to the ret_nilable method, because that’s the one which can return nil.

5.times do |n|
  val = ret_nilable(n).try { |x| x[:v1] }
  # Also, can be folded like this:
  val = ret_nilable(n).try &.[:v1]
  puts "#{n}: #{val}"
end

Thanks @sudo-nice. So, I need to drop the ?. It works without the ?. I need to understand the use of ? better.

Thanks again.

There’s no ? in the language. ? can be the last letter of a method name. For example first and first?. Or [] and []?. And generally when two such methods exist, the one without ? will raise on nil while the one with ? will return nil.

Thanks for clarifying that @asterite. I understand now.

1 Like