将用户输入转换为整数时,为什么在Crystal中需要.to_s方法?

Aar*_*ron 2 ruby string crystal-lang

我开始使用Crystal,但遇到了一些我不了解的问题。我编写了一个简单的程序来演示,该程序从控制台获取一个数字并添加一个。

红宝石

# Add one program.
puts "Enter a number."

number = gets

number = number.to_i

puts "You entered #{number}. #{number} + 1 = #{number + 1}"
Run Code Online (Sandbox Code Playgroud)

水晶

# Add one program.
puts "Enter a number."

number = gets

number = number.to_s.to_i # Why is to_s needed?

puts "You entered #{number}. #{number} + 1 = #{number + 1}"
Run Code Online (Sandbox Code Playgroud)

如您所见,程序几乎相同,但是在Crystal中,我必须从控制台获取输入并将其转换为字符串,然后才能将其转换为整数。

我想知道的是:

  • 水晶返回的是什么?
  • 没有链接方法,还有另一种方法吗?

这似乎是一个基本问题,但对于Crystal来说仍处于早期阶段,并且文档稀疏。

错误

Error in example.cr:6: undefined method 'to_i' for Nil (compile-time type is (String | Nil)) (did you mean 'to_s'?)

number = number.to_i # Why is to_s needed?
                ^~~~

================================================================================

Nil trace:

  example.cr:4

    number = gets
    ^~~~~~

  example.cr:4

    number = gets
             ^~~~

  /usr/share/crystal/src/kernel.cr:105

    def gets(*args, **options)


  /usr/share/crystal/src/kernel.cr:105

    def gets(*args, **options)
              ^

  /usr/share/crystal/src/kernel.cr:106

      STDIN.gets(*args, **options)
            ^~~~

  /usr/share/crystal/src/io.cr:574

      def gets(chomp = true) : String?


  /usr/share/crystal/src/io.cr:574

      def gets(chomp = true) : String?
               ^

  /usr/share/crystal/src/io.cr:574

      def gets(chomp = true) : String?


  /usr/share/crystal/src/io.cr:574

      def gets(chomp = true) : String?
          ^~~~

  /usr/share/crystal/src/io.cr:575

        gets '\n', chomp: chomp
        ^~~~

  /usr/share/crystal/src/io.cr:604

      def gets(delimiter : Char, chomp = false) : String?
          ^~~~

  /usr/share/crystal/src/io.cr:605

        gets delimiter, Int32::MAX, chomp: chomp
        ^~~~

  /usr/share/crystal/src/io.cr:618

      def gets(delimiter : Char, limit : Int, chomp = false) : String?
          ^~~~

  /usr/share/crystal/src/io.cr:619

        raise ArgumentError.new "Negative limit" if limit < 0
        ^

  /usr/share/crystal/src/io.cr:632

        if ascii && !decoder && (peek = self.peek)
        ^

  /usr/share/crystal/src/io.cr:633

          if peek.empty?
          ^

  /usr/share/crystal/src/io.cr:634

            nil
            ^
Run Code Online (Sandbox Code Playgroud)

spi*_*ann 5

在大多数情况下,gets将返回String,但也有可能返回nil

这在Ruby中不是问题,因为在您的示例中,您将nil在运行时返回,即使您在运行时NilClass#to_i,Ruby中也始终会返回0

但是Crystal编译器会预先检查对象类型,因此确保您的代码可以处理所有可能的返回类型。不幸的是,在Crystal中,尚无任何to_i方法Nil,因此会出现编译器错误:

undefined method 'to_i' for Nil (compile-time type is (String | Nil))
Run Code Online (Sandbox Code Playgroud)

  • 零不等于零。通常,您不希望这样的隐式转换。如果nil.to_i返回0,则很容易导致错误。在Crystal中,编译器会警告您有关零值的问题,并要求明确对待它们。如果要对nil进行整数转换以得出0,则需要显式编写,例如使用number.try(&。to_i)||。0`。 (5认同)