【问题标题】:In this case, how do I handle nil well?在这种情况下,我如何处理好 nil ?
【发布时间】:2021-08-18 09:25:08
【问题描述】:

情况

我写了以下代码。

class Gear
  getter :chainring, :cog, :wheel

  def initialize(@chainring : Int32, @cog : Int32, @wheel : Wheel?)
  end

  def ratio
    chainring / cog.to_f
  end

  def gear_inches
    ratio * wheel.diameter
  end
end

然后出现如下编译错误

$ crystal run  gear.cr 
Showing last frame. Use --error-trace for full trace.

In bicycle.cr:12:19

 12 | ratio * wheel.diameter

我想做的事

我想在不使用try 方法的情况下修复这个编译错误。

我尝试了什么,我研究了什么

  1. Crystal 语言不允许使用安全导航运算符。
  2. 仅当 wheel 变量为真时才执行 diameter 方法,如 TypeScript 中所示。示例如下。
def gear_inches
  if wheel
    ratio * wheel.diameter
  else
    0
  end
end

问题就是这样。 如果您能给我任何建议,我将不胜感激。

【问题讨论】:

    标签: crystal-lang


    【解决方案1】:

    在并发程序中,实例变量的值可以在任何两次访问之间改变。 getter wheel 使wheel 只返回实例变量@wheel。因此,在检查 if wheel 和第二次调用 wheel.diameter 之间,Crystal 无法判断该值不可能改变。

    通常的解决方案是将值分配给局部变量,这允许 Crystal 推断值何时无法更改:

    record Wheel, diameter : Int32
    
    class Gear
      getter :chainring, :cog, :wheel
    
      def initialize(@chainring : Int32, @cog : Int32, @wheel : Wheel?)
      end
    
      def ratio
        chainring / cog.to_f
      end
    
      def gear_inches
        (wheel = self.wheel) ? ratio * wheel.diameter : 0
      end
    end
    
    gear = Gear.new(1, 2, Wheel.new(3))
    puts gear.gear_inches
    

    在许多情况下,一个不错的选择是查看您是否可以找到一个默认值以在内部为您的可选字段返回:

    record Wheel, diameter : Int32
    
    class Gear
      getter :chainring, :cog
    
      def initialize(@chainring : Int32, @cog : Int32, @wheel : Wheel?)
      end
    
      def ratio
        chainring / cog.to_f
      end
    
      def gear_inches
        ratio * wheel.diameter
      end
      
      private def wheel
        @wheel || Wheel.new(0)
      end
    end
    
    gear = Gear.new(1, 2, nil)
    puts gear.gear_inches
    

    【讨论】:

    • 感谢您的回答!我充满感激。我对并发编程一无所知。我很高兴知道为什么我写的程序给了我一个编译错误。此外,您回答的代码非常容易理解!我将以此为参考重写我的代码。非常感谢!
    猜你喜欢
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-16
    • 1970-01-01
    • 1970-01-01
    • 2017-09-12
    相关资源
    最近更新 更多